javascripts如何扩展工作?

时间:2017-12-09 12:39:33

标签: javascript ecmascript-6 prototype extends

更新:@Bergi在this thread上发帖说明需要使用Reflect.construct而不是仅调用父构造函数。这将问题转移到" Constructor.call()和Reflect.construct()"之间的技术差异。感谢所有的评论。

很长一段时间以来,我一直在通过将我的新原型的原型设置为要扩展的原型来扩展各种类型。例如。如果我想扩展课程" Person"我通过调用NewType.prototype=Object.create(Person.prototype);来创建我的扩展原型,例如:

const B = function(){
    return A.call(this);
};

B.prototype = Object.create(A.prototype);

B.prototype.extra_method = function(){
    console.log('hello');
}

最近我注意到这个方法不如ES6 class extends那么强大。例如,如果我想扩展内置类型,我只能使用类extends关键字来实现。这是为什么?  

示例A (不起作用):

const ArrayExt = function(){
    this.extra_variable = 'hello!';
    return Array.call(this,...arguments); 
}

ArrayExt.prototype = Object.create(Array.prototype);

ArrayExt.prototype.extra_method = function(){
    console.log('Method called!');
}

var inst = new ArrayExt(1,2,3);

inst.push(4);
inst.length == 4 //seems to work right?

inst.extra_method == undefined //not included
inst.extra_variable == undefined //not included (why?)


示例B (正常):

const ArrayExt = class extends Array{
    constructor(){
        super(...arguments);
        this.extra_variable = 'Hello!';
    }

    extra_method(){
        console.log('I actually am here now!');
    }
};

var inst = new ArrayExt(1,2,3);

inst.push(4);
inst.length == 4 //works
inst.extra_variable == 'Hello!' //works
inst.extra_method() //'I actually am here now!' works

1 个答案:

答案 0 :(得分:1)

  

Constructor.call()和Reflect.construct()

之间的技术差异是什么?

它是功能对象的不同用法。它与Example()new Example()之间的差异相同。

这两个表达式总是做不同的事情,解析为一个对象可以拥有的两个不同的内部方法(名为[[call]][[construct]])。 ES6刚刚引入了新类型的函数,其中只有一个函数可用(箭头,方法:call; class constructors:construct)。从function语法创建的函数总是启用两者(即使它不合适)。