class

作者: 欢西西西 | 来源:发表于2023-03-23 17:32 被阅读0次
    
    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. 实现私有属性的方法的方式
    

    相关文章

      网友评论

          本文标题:class

          本文链接:https://www.haomeiwen.com/subject/sbiirdtx.html