美文网首页
ES6中的Class

ES6中的Class

作者: 樱木夜访流川枫 | 来源:发表于2018-04-25 23:41 被阅读0次

    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
    

    相关文章

      网友评论

          本文标题:ES6中的Class

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