这两个构造函数在JavaScript中有什么区别?

时间:2014-04-08 16:46:30

标签: javascript object prototypal-inheritance

在MDN' s page for Call上有3个构造函数的示例:Product,Food和Toy

function Product(name, price) {
    this.name = name;
    this.price = price;

    if (price < 0)
        throw RangeError('Cannot create product "' + name + '" with a negative price');
    return this;
}

function Food(name, price) {
    Product.call(this, name, price);
    this.category = 'food';
}
Food.prototype = Object.create(Product.prototype);

为什么这条线是必要的?

Food.prototype = Object.create(Product.prototype);

我不能这样做吗?

function Food (name, price) {
    var me = Product.call(this, name, price);
    me.category = 'food';
    return me;
}

2 个答案:

答案 0 :(得分:1)

不同之处在于您的对象Food不会继承Product的原型方法。它返回看起来像Product的实例的内容,但存在差异。

答案 1 :(得分:1)

一个区别是语法。在我看来,它在第一个片段中更好。

基本上这个:

Food.prototype = Object.create(Product.prototype);

以及稍后的

Toy.prototype = Object.create(Product.prototype);

意味着他们共享相同的产品原型,这很好。但是在你向我们展示的例子中,他们并没有真正利用class这个概念,而这个概念在JavaScript中并不存在,但在必须语言中是活跃的(例如PHP)。

您可以将功能或属性仅附加到玩具或食物上:

Food.prototype = Object.create(Product.prototype);
Food.prototype.eat = function(){ //Toy object can't call that function
    alert('Om Nom Nom')
}

当然你也可以这样做:

function Food (name, price) {
    var me = Product.call(this, name, price);
    me.category = 'food';
    me.eat = function(){
        alert('Om Nom Nom');
    };
    return me;
}

但这会导致不必要的内存使用并可能影响性能。

最后,使用instanceof将是错误的。使用第二种方法,您将无法知道对象是否是产品:

//Method1
alert(foodObj instanceof Food); //true
alert(foodObj instanceof Product); //true

//Method2
alert(foodObj instanceof Food); //true
alert(foodObj instanceof Product); //false

Live example