这两种方法的区别是什么?
// Shape - superclass
function Shape() {
this.x = 0;
this.y = 0;
}
// superclass method
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
};
// Rectangle - subclass
function Rectangle() {
Shape.call(this);
}
// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();
// Shape - superclass
function Shape() {
this.x = 0;
this.y = 0;
}
// superclass method
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
};
// Rectangle - subclass
function Rectangle() {
Shape.call(this);
}
// subclass extends superclass
Rectangle.prototype = new Shape();
var rect = new Rectangle();
答案 0 :(得分:2)
我看到两个不同:一个大,一个小。
不同之处在于,在第二种方法中,Rectangle
原型不会正确设置constructor
属性。它将指向Shape
,而不是Rectangle
。这在JavaScript OO方法中是一个非常常见的错误,并且大多数情况下你可以逃脱它,因为人们不会非常使用constructor
属性,但它就在那里。
最大的区别是第二个构造函数中对Shape()
的额外调用。在您的特定示例中,事情或多或少都可以正常运行:Rectangle.prototype
有一些额外的属性(x
和y
,两者都等于零),您可能不打算这样做但是,无论如何,这些都会被Rectangle
实例中的相应属性所掩盖。再一次,这种非常常见但很小的bug经常足以让你逃脱它。
第二种方法的问题是它只在超类构造函数不需要任何参数时才有效。您的示例恰好符合该描述,因为它所做的只是将某些属性初始化为默认值。但是存在这种设置不合适的用例,并且在这些情况下不能使用第二种方法。
答案 1 :(得分:1)
主要区别在于,在第二种方法中,Shape
构造函数只被调用一次。在第一种方法中,不调用Shape
构造函数,而是Object.create(Shape.prototype)
从原型创建一个新对象。然后可以使用Shape.call
每个子构造调用一次父构造函数。
您仍然可以为每个子类调用Shape.call
,如第二种方法,但它会在初始原型创建期间对构造函数进行额外调用。
此外,使用Object.create
的第一种方法会导致constructor
的{{1}}属性被覆盖,因此prototype
用于重置Rectangle.prototype.constructor = Rectangle;
属性。
答案 2 :(得分:1)
第二种方法的主要缺点是它需要额外调用Shape
构造函数,以便创建一个对象作为Rectangle
的原型。有不同的方法可以避免它,例如中间空函数:
function Rectangle() {
Shape.call(this);
}
function f() {}
f.prototype = Shape.prototype;
Rectangle.prototype = new f();
如你所见,这显然非常笨拙。
出于这个原因,使用Object.create
的模式#1更为方便和有效。
但请注意,两个片段都有另一个问题:使用Shape.call(this);
复制自己的属性,这也是不可取的。
答案 3 :(得分:0)
Object.create不执行构造函数。
使用New调用等效于Object.create(object.prototype)+运行构造函数。
答案 4 :(得分:-1)
最大的实际区别是,当你使用new时,将调用超类的构造函数,而不需要Shape.call(this);
。