es5实现class类

作者: 羽晞yose | 来源:发表于2020-10-16 21:04 被阅读0次

    es5没有类,只有构造函数。ES6新增了class,用于创建类。本文通过es5来实现es6的class(一个Animal类),让初学者对类的特点及底层原理有更深刻的理解

    特点

    1. 只能通过new来调用,否则会抛出类型错误(类的调用检测)
      解决方法:通过构造函数内this指向来判断抛出错误
    function Animal () { // 只能通过new来调用
        this.name = '熊猫'; // 实例属性
    
        if (!(this instanceof Animal)) {
            throw TypeError(`Class constructor An cannot be invoked without 'new'`);
        }
    }
    
    // Animal(); // 报错,直接调用
    
    let animal = new Animal();
    console.log(animal)
    
    1. 原型上的属性和方法可被继承,但不可枚举
      根据babel实现方式,开发一个defineProperty方法来批量添加

    Object.defineProperty()
    直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
    MDN文档链接地址

    // 定义原型属性及方法
    function defineProperty (constructor, protoProperties, staticProperties) {
        // 有传入需要定义的原型属性和方法
        if (Array.isArray(protoProperties)) {
            define(constructor.prototype, protoProperties)
        }
    
        // 有传入需要定义的静态属性和方法
        if (Array.isArray(staticProperties)) {
            define(constructor, staticProperties)
        }
    }
    
    function define (target, protoProperties) {
        for(let i = 0; i < protoProperties.length; i++) {
            let property = protoProperties[i];
            let {key, ...config} = property;
    
            Object.defineProperty(target, key, {
                configurable: true,
                enumerable: false, // 不可枚举,通过prototype是看不到的
                ...config
            });
        }
    }
    
    let Animal = (function () {
        function ClassModel () {
            if (!(this instanceof ClassModel)) {
                throw TypeError(`Class constructor An cannot be invoked without 'new'`);
            }
        }
    
        defineProperty(ClassModel, [
            {
                key: 'age',
                value: 10
            }, {
                key: 'eat',
                value: function () {
                    console.log('eat');
                }
            }
        ], [
            {
                key: 'chineseName',
                value: '佳佳'
            }, {
                key: 'like',
                value: function () {
                    console.log('吃竹子');
                }
            }
        ])
    
        return ClassModel;
    })();
    
    let animal = new Animal();
    console.log(Animal.prototype) // 检查原型属性与方法是否被枚举出来
    console.log(Animal.chineseName); // 静态属性
    
    node执行结果
    注意:由于在浏览器中,不可枚举属性只对以下方式有效,所以浏览器中依然可以看到属性被枚举出来,使用node执行prototype才会是空对象
    • for…in循环
    • Object.keys方法
    • JSON.stringify方法

    推荐vscode安装code runner插件,这样就不需要在外面跑这种代码片段了

    相关文章

      网友评论

        本文标题:es5实现class类

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