欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

ES6中的Class

程序员文章站 2023-12-21 13:03:04
...

ES6的class语法 不是一种新的“类”机制,class基本上只是现有 [[prototype]]链(委托)机制的语法糖。

内容

代码如下:

// widget:部件,button:按钮
class Widget {
    constructor(width,height) {
        this.width = width || 50;
        this.height = height || 50;
        this.$elem = null;
    }
    render($where){
        if (this.$elem) {
            this.$elem.css( {
                width: this.width + "px",
                height: this.height + "px"
            } ).appendTo( $where );
        }
    }
}

class Button extends Widget {
    constructor(width,height,label) {
        // 解决相对多态
        super( width, height );
        this.label = label || "Default";
        this.$elem = $( "<button>" ).text( this.label );
    }
    render($where) {
        super.render( $where );
        this.$elem.click( this.onClick.bind( this ) );
    }
    onClick(evt) {
        console.log( "Button '" + this.label + "' clicked!" );
    }
}

代码分析:
1、在写法上,更符合面向对象中类的写法。
2、使用 extends关键字实现委托,不再需要 Object.create()来替换 .prototype指向的对象,不再需要设置 .proto或者 Object.setPrototypeOf()
3、使用 super()实现 相对多态,改变了this绑定这种显示假想多态技术。
4、class字面语法 不能声明属性(只能声明方法)。这种限制解决了 原型链末端可能意外的获取其他地方的属性。
5、class ... extends这种语法更易于扩展 对象子类型

class陷阱

class语法并没有解决所有的问题,在JavaScript中使用这种模式仍然存在许多深层问题。

陷阱1 不是静态拷贝

代码如下:

class C {
    constructor() {
        this.num = Math.random();
    }
    rand() {
        console.log( "Random: " + this.num );
    }
}

var c1 = new C();
c1.rand(); // "Random: 0.4324299..."

C.prototype.rand = function() {
    console.log( "Random: " + Math.round( this.num * 1000 ));
};

var c2 = new C();
c2.rand(); // "Random: 867"

c1.rand(); // "Random: 432" -- oops!!!

代码分析:
ES6 class语法不是一种新的“类”机制,不是在声明时静态拷贝定义,仍是[prototype]链(委托)机制的语法糖。所以,对 父“类”的修改都会影响到子类和子类的实例对象

严格声明:在面向对象的其它语言中,以Java为例,声明父类Class A,再声明Class B 继承自Class A,此时如果修改了父类Class A的方法Fn1,修改后需要重新编译: 如果Fn1在Class B中已经 重写,那么Class B中的Fn1将不会受到Class A修改后的影响;如果Class B没有重写,Class B中的Fn1将会受到Class A修改后的影响。

陷阱2 .prototype实现细节暴露

ES6 Class语法不能直接声明属性,需要借助 .prototype语法,违背了ES6 class语法的初衷。

class C {
    constructor() {
        // 确保修改的是共享状态
        // 不是设置实例上的遮蔽属性
        C.prototype.count++;

        // 这里,`this.count`通过委托如我们期望的那样工作
        console.log( "Hello: " + this.count );
    }
}

// 直接在原型对象上添加一个共享属性
C.prototype.count = 0;

var c1 = new C();
// Hello: 1

var c2 = new C();
// Hello: 2

c1.count === 2; // true
c1.count === c2.count; // true

转载于:https://www.jianshu.com/p/7311dd3e9457

上一篇:

下一篇: