ES6之对Class降级

0 阅读2分钟

ES6之对Class降级

如何将 ES6 降级到 ES5 ,这里有一个例子,结合之前的知识进行讲解:

//ES6降级ES5
// class Product {
//     static count = 0;
//     constructor(name, unitPrice, number) {
//         this.name = name;
//         this.unitPrice = unitPrice;
//         this.number = number;
//         Product.count++;
//     }
//     get totalPrice() {
//         return this.unitPrice * this.number;
//     }
//     increase() {
//         this.number++;
//     }
// }
// console.log(new Product(),'before')
// 不能提前调用构造函数,会报错
var Product = (() => {
    function Product(name, unitPrice, number) {
        //官方不推荐使用this.__proto__
        //防止不使用new调用
        // console.log(this.__proto__,'this.__proto__')
        if (Object.getPrototypeOf(this) !== Product.prototype) {
            throw new TypeError("Class constructor Product cannot be invoked without 'new'")
        }
        this.name = name;
        this.unitPrice = unitPrice;
        this.number = number;
        Product.count++;
        //原型和实例里都需要get属性
        Object.defineProperty(this, 'totalPrice', {
            get() {
                return this.unitPrice * this.number;
            },
            enumerable: false,//不可枚举
        })
    }
    // 给原型上添加一个属性totalPrice,这样可以直接调用属性,后面描述了属性的行为
    Object.defineProperty(Product.prototype, 'totalPrice', {
        get() {
            return this.unitPrice * this.number;
        },
        enumerable: false,//不可枚举
    })
    Product.count = 0;
    //由于原型上的方法不可枚举,所以使用Object.defineProperty形式定义
    Object.defineProperty(Product.prototype,'increase',{
        enumerable: false,
        value: function () {
            //如果指向原型,说明通过new调用,规定不能通过new调用
            if(Object.getPrototypeOf(this)===Product.prototype.increase.prototype){
                throw new TypeError('increase is not a constructor')
                // console.log(this,'普通')
            }
            console.log(this)
            this.number++;
        }
    })
    return Product;
})()
const p=new Product(1,2,3);
console.log(new p.increase(), 'after')

我们首先将 constructor,static ,increase 降级成构造函数的形式,static 是构造函数的静态方法,increase 是原型上的方法。
我们注意到如果在声明之前调用会报错,所以将整个内容包装在一个立即执行函数中,并返回一个 Product ,这样在之前调用返回的是 undefined 。
而且构造函数只能通过 new 调用,我们判断如果 this 没有指向原型,则一定是普通函数调用需要报错。这里不推荐使用 this._proto_ 的方式。
我们注意到还有一个 get 属性,我们使用 defineProperty 给原型添加一个 get 属性,后面可以直接执行属性的行为。并且需要增加不可枚举的属性。同时,在原型和实例中都需要写一次,因为两个地方都会出现。
最后对 increase 进行改造,由于也不可枚举所以也使用 defineProperty 的方式,同时当使用 new 调用时需要报错,可以通过判断 this 的指向是否指向函数的原型,如果指向原型,则一定是通过 new 来调用。