function _typeof(obj) {
"@babel/helpers - typeof";
return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator
? function (obj) { return typeof obj; }
: function (obj) {
return obj && "function" == typeof Symbol
&& obj.constructor === Symbol &&
obj !== Symbol.prototype ? "symbol" : typeof obj;
}, _typeof(obj);
}
function _defineProperties(target, props) {
for (var i = 0; i < props.length; i++) {
var descriptor = props[i];
descriptor.enumerable = descriptor.enumerable || false;
descriptor.configurable = true;
if ("value" in descriptor) descriptor.writable = true;
Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
}
}
function _createClass(Constructor, protoProps, staticProps) {
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
if (staticProps) _defineProperties(Constructor, staticProps);
Object.defineProperty(Constructor, "prototype", { writable: false });
return Constructor;
}
function _toPropertyKey(arg) {
var key = _toPrimitive(arg, "string");
return _typeof(key) === "symbol" ? key : String(key);
}
function _toPrimitive(input, hint) {
if (_typeof(input) !== "object" || input === null)
return input;
var prim = input[Symbol.toPrimitive];
if (prim !== undefined) {
var res = prim.call(input, hint || "default");
if (_typeof(res) !== "object")
return res;
throw new TypeError("@@toPrimitive must return a primitive value.");
}
return (hint === "string" ? String : Number)(input);
}
function _classCallCheck(instance, Constructor) {
if (!(instance instanceof Constructor)) {
throw new TypeError("Cannot call a class as a function");
}
/**
* 因为class声明的类只能使用new来调用,否则会报错
* 表示这个构造函数不应该被当做普通函数调用
* 其实这里没有做到识别new,如果更改this指向就能绕过这个校验:var p = new Person(); Person.call(p);
*
* https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Operators/new.target
* 而使用new.target可以检测一个函数是否是作为构造函数通过new被调用的
* function Test(){ console.log('谁调用呢,嗯?', new.target); }
*/
}
function _defineProperty(obj, key, value) {
key = _toPropertyKey(key);
if (key in obj) {
Object.defineProperty(obj, key,
{
value: value,
enumerable: true,
configurable: true,
writable: true
});
} else {
obj[key] = value;
}
return obj;
}
var Person = /*#__PURE__*/_createClass(function Person() {
_classCallCheck(this, Person);
});
// #region ES5
function Person() { }
// 编译结果
function _Person() {
_classCallCheck(this, _Person);
}
var Person = /*#__PURE__*/_createClass(_Person);
// Marks a function call as pure. That means, it can safely be dropped.
// 是可以告诉 webpack 一个函数调用是无副作用的
// 如果一个没被使用的变量定义的初始值被认为是无副作用的(pure),它会被标记为死代码,可以被安全删除
// https://www.webpackjs.com/guides/tree-shaking/#root
// #endregion
// #region 增加实例属性和原型方法
// class Company {
// address = 'hangzhou';
// constructor(name) {
// this.name = name;
// this._init();
// }
// _init() { }
// getDisplayAddress() {
// return `${this.name}:${this.address}`;
// }
// }
// ES5
function Company(name) {
this.address = 'hangzhou';
this.name = name;
this._init();
}
Company.prototype = {
constructor: Company,
_init: function () { },
getDisplayAddress: function () {
return `${this.name}:${this.address}`;
}
};
// 编译后
var Company = /*#__PURE__*/function () {
function Company(name) {
_classCallCheck(this, Company);
_defineProperty(this, "address", 'hangzhou');
this.name = name;
this._init();
}
_createClass(Company, [{
key: "_init",
value: function _init() { }
}, {
key: "getDisplayAddress",
value: function getDisplayAddress() {
return "".concat(this.name, "\uFF1A").concat(this.address);
}
}]);
return Company;
}();
// #endregion
// #region 增加静态属性和静态方法
// class Company {
// static address = 'hangzhou'
// static getDisplayAddress() {
// return `${this.name}:${this.address}`; // Company.getDisplayAddress()
// }
// }
// 使用static修饰,使属性和方法挂在构造函数对象上
// 例如jQuery.ajax, ajax就挂在jQuery这个构造函数上,而不在它的prototype上,所以jQuery实例也不会访问到ajax方法
// Promise.all 和 Promise.prototype.then
// Vue.version挂在Vue这个构造函数上
// 编译后
var Company = /*#__PURE__*/function () {
function Company() {
_classCallCheck(this, Company);
}
_createClass(Company, null, [{
key: "getDisplayAddress",
value: function getDisplayAddress() {
return "".concat(this.name, "\uFF1A").concat(this.address);
}
}]);
return Company;
}();
_defineProperty(Company, "address", 'hangzhou');
// #endregion
// #region 增加私有属性和方法
// 【1】声明时使用下划线
// 【2】使用Symbol定义私有属性
// Object.getOwnPropertySymbols()获取
// 【3】哈希前缀 #
// MDN: https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes/Private_class_fields
// 浏览器兼容性:https://caniuse.com/?search=Private%20class%20fields
// static 和 非static 的区别是:定义在prototype上还是类本身上
// # 和 非# 的区别是:实例是否可以访问
// class Company {
// #privateField;
//
// constructor() {
// console.log(this.#privateField);
// this.#init();
// }
// #init() {
// this.#privateField = '仅内部使用';
// }
// }
// babel的思路
// ——通过生成外部的属性和方法
var _privateField;
function _init() {
_privateField = '仅内部使用';
}
function Company() {
console.log(_privateField);
_init.call(this);
}
// 多个实例,就需要保存多个_privateField
function _classPrivateMethodInitSpec(obj, privateSet) {
_checkPrivateRedeclaration(obj, privateSet);
privateSet.add(obj);
}
function _classPrivateFieldInitSpec(obj, privateMap, value) {
// 在privateMap中存实例和该属性的映射关系
_checkPrivateRedeclaration(obj, privateMap);
privateMap.set(obj, value);
}
function _checkPrivateRedeclaration(obj, privateCollection) {
if (privateCollection.has(obj)) {
throw new TypeError("Cannot initialize the same private elements twice on an object");
}
}
function _classPrivateMethodGet(receiver, privateSet, fn) {
if (!privateSet.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance");
}
return fn;
}
function _classPrivateFieldSet(receiver, privateMap, value) {
var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); // 获取descriptor
_classApplyDescriptorSet(receiver, descriptor, value); // 设置value
return value;
}
function _classExtractFieldDescriptor(receiver, privateMap, action) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to " + action + " private field on non-instance");
}
return privateMap.get(receiver);
}
function _classPrivateFieldGet(receiver, privateMap) {
var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); // 获取descriptor
return _classApplyDescriptorGet(receiver, descriptor);
}
function _classApplyDescriptorGet(receiver, descriptor) {
if (descriptor.get) {
return descriptor.get.call(receiver);
}
return descriptor.value;
}
function _classApplyDescriptorSet(receiver, descriptor, value) {
if (descriptor.set) {
descriptor.set.call(receiver, value);
}
else {
if (!descriptor.writable) {
throw new TypeError("attempted to set read only private field");
}
descriptor.value = value;
}
}
var _privateField = /*#__PURE__*/new WeakMap();
var _init = /*#__PURE__*/new WeakSet();
var Company = /*#__PURE__*/_createClass(function Company() {
_classCallCheck(this, Company);
_classPrivateMethodInitSpec(this, _init); // 把这个实例添加到_init里面
_classPrivateFieldInitSpec(this, _privateField, { // 【初始化】:在WeakMap中设置{[this]: config}
writable: true,
value: void 0
});
console.log(_classPrivateFieldGet(this, _privateField)); // 【访问】
_classPrivateMethodGet(this, _init, _init2).call(this); // 访问私有方法:调用_init2
});
function _init2() {
_classPrivateFieldSet(this, _privateField, '仅内部使用'); // 【修改】
}
// #endregion
// 1. 原型方法和静态方法的区别
// 2. 检查构造函数是否是由new调用的
// 3. 实现私有属性的方法的方式
网友评论