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