这些原型声明有什么区别?

时间:2013-05-27 12:17:51

标签: javascript oop prototype

方法1:

Rectangle.prototype.getArea = function() {
     return this.length * this.width;
};

方法2:

Rectangle.prototype = {
     getArea: function() {
          return this.length * this.width;
     }
};

上述每种方法的不同之处和优点是什么?

3 个答案:

答案 0 :(得分:4)

第二个会破坏继承链并删除之前添加到原型中的所有属性。

让我们通过这个例子来看看“继承链中断”的含义:

function A(){}
A.prototype.a = function(){}
function B(){}
B.prototype = new A();
B.prototype.b = function(){}

此处的B实例会继承a方法。

但如果你这样做

B.prototype = { b: function(){} }

然后情况就不再如此了。

答案 1 :(得分:4)

在第一种情况下,您新属性添加到现有对象,在第二种情况下,您使用新值覆盖 Rectangle.prototype )。

覆盖原型会产生以下后果:

  • Rectangle.prototype.constructor不再指向Rectangle。当您使用对象文字时,它将指向Object。通过分配

    可以轻松解决这个问题
    Rectangle.prototype.constructor = Rectangle;
    
  • 您可能会丢失原型上的所有现有属性(除非您再次添加它们,例如constructor)。

  • Rectangle的现有实例不会受到更改的影响。他们仍然会引用旧的原型,并且不会继承新的方法/属性。

  • instanceof现有实例(即rect instanceof Rectangle)的测试将失败,因为instanceof会比较原型和在前一点中提到,现有实例保留了对旧原型的引用。

如果在创建任何实例之前设置原型,那么您不必关心最后三点。

  

上述每种方法的不同之处和优点是什么?

使用对象文字覆盖原型的唯一优势是更简洁的语法。 IMO虽然没有超过缺点。

您可以通过合并两个对象来使用对象文字而不覆盖原型:How can I merge properties of two JavaScript objects dynamically?

答案 2 :(得分:1)

如果Rectangle.prototype{},则两种方法之间没有区别。