为什么我们需要在JavaScript
我读这段代码为什么我们需要在JavaScript
// Shape - superclass
function Shape() {
this.x = 0;
this.y = 0;
}
// superclass method
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
};
// Rectangle - subclass
function Rectangle() {
Shape.call(this); // call super constructor.
}
// subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
var rect = new Rectangle();
rect instanceof Rectangle; // true
rect instanceof Shape; // true
rect.move(1, 1); // Outputs, 'Shape moved.'
我真是被这个片段迷惑
Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.constructor = Rectangle;
为什么我们不使用Rectangle.prototype =形状。原型,Object.create()
有什么特别之处? 以及如果Rectangle.prototype.constructor = Rectangle;不叫?
如果你做Rectangle.prototype = Shape.prototype
那么你将在Rectangle.prototoype
上执行的任何修改将反映在Shape.prototype
上,因为它们是相同的对象。
为了避免这种情况,我们使用Object.create(Shape.prototype)
创建一个新对象,该对象的原型链接指向Shape.prototype
。
至于Rectangle.prototype.constructor = Rectangle;
,这是为了确保new Shape().constructor
指向Rectangle
而不是Shape
。
函数的原生prototype
具有指向该函数的constructor
属性。
例如
function Rectangle() {}
Rectangle.prototype.constructor === Rectangle; //true
现在,当我们做Rectangle.prototype = ...
,我们打破参考,并需要事后修复。
如果您只是将Rectangle.prototype
设置为Shape.prototype
,那么Rectangle
和Shape
将与原型共享同一个对象。这意味着,您添加到Rectangle.prototype
的所有内容也可在Shape.prototype
上获得 - Rectangle
将不再继承自Shape
。
Object.create(parent)
创建一个从传入的父对象继承的子对象。这样,父对象的所有属性也可用于子对象,而子对象的属性不会影响父对象。
要回答你的问题(“为什么我们需要在JavaScript中定义构造函数?”) - 我们不需要。您也可以使用普通对象:
// Shape - superclass
function Shape() {
return {
x: 0,
y: 0,
// superclass method
move: function(x, y) {
this.x += x;
this.y += y;
console.info('Shape moved.');
}
};
}
// Rectangle - subclass
function Rectangle() {
var rectangle = Shape();
// rectangle-specific things could be added here
return rectangle;
}
var rect = Rectangle();
rect instanceof Rectangle; // false, instanceof does not work here
rect instanceof Shape; // false
rect.move(1, 1); // Outputs, 'Shape moved.'
你的非构造函数样本不太纯粹,而且很具误导性。以下是你应该做的事情'var shape = {...}; var rectangle = Object.create(shape); //添加矩形东西var r1 = Object.create(rectangle);' – plalx 2014-12-04 22:17:24
请原谅我编写不太纯的示例。我只是想证明我们不受JavaScript中“类的”继承的束缚。纯净不是我最关心的问题。不过,我不同意这个例子有误导性。 Shape()在每次调用时都会返回一个新形状。通过'Object.create()'继承它没有任何好处。直接扩展该对象是完全可能的和安全的。 – 2014-12-04 22:22:18
好吧,这是误导性的,因为有一个广泛的命名约定,它说上层函数应该是构造函数,但即使你修正了这个问题,你的代码在内存方面仍然效率低下,因为你没有通过原型分享任何东西。在执行方面也是低效的,例如,您将不得不每次创建新创建的形状对象以创建矩形实例。所有这些都通过像我建议的那样使用Object.create来解决,这是避免构造函数的标准方法。 – plalx 2014-12-04 22:48:34
'为什么我们不使用Rectangle.prototype = Shape.prototype'矩形是一个形状,但不是每个形状都是矩形。改变Rectangle.prototype会改变Shape.prototype。如果有人想要使用它(和Chrome中的控制台日志记录),构造函数会进行一致性修复。更多关于构造函数,原型,继承,混合ins等在这里:http://stackoverflow.com/a/16063711/1641941 – HMR 2014-12-05 02:40:27