function Rectangle(length, width) {
this.length = length;
this.width = width;
}
Rectangle.prototype.getArea = function() {
return this.length * this.width;
};
function Square(size) {
this.length = size;
this.width = size;
}
Square.prototype = new Rectangle();
那是我的代码。
Square是否正确继承自Rectangle?请建议我所做的更改以正确执行操作。
继承和原型(prototype)的新手。
最佳答案
不,但是很近。这是Square
的更改:
function Square(size) {
Rectangle.call(this, size, size);
}
Square.prototype = Object.create(Rectangle.prototype);
Square.prototype.constructor = Square;
调用
Rectangle
创建Square
的原型(prototype)是一种可悲的反模式。如果它实际上对我们在这样做时没有给出的参数有什么影响,该怎么办?而是使用
Rectangle.prototype
创建一个使用Object.create
作为其原型(prototype)的对象。然后,在该原型(prototype)上更新constructor
属性,使其指向正确的函数。然后,当您实际上有一个要初始化的对象时(例如,在Square
函数中),您可以从Rectangle
调用Square
对其位进行初始化,然后再进行Square
的进一步初始化。由于有点冗长,因此在切换到ES2015
class
语法之前,我为此使用了一个辅助脚本 Lineage
。可以将创建原型(prototype)的位隔离为一个函数,这也使我们有机会通过解决IE8缺少Object.create
的事实来支持IE8:function derivePrototype(parent, child) {
var proto, ctor;
if (Object.create) {
proto = Object.create(parent.prototype);
} else {
ctor = function ctor() { }; // * See note
ctor.prototype = parent.prototype;
proto = new ctor;
ctor = null;
}
proto.constructor = child;
return proto;
}
然后
Square.prototype = derivePrototype(Rectangle, Square);
*
ctor = function ctor() { };
在IE8上创建了两个函数(details),但由于没有保留任何内容,因此它是无害的,并且该函数的确获得了名称。或者,当然,您可以使用ES2015 +:
class Rectangle {
constructor(length, width) {
this.length = length;
this.width = width;
}
getArea() {
return this.length * this.width;
}
}
class Square extends Rectangle {
constructor(size) {
super(size, size);
}
}
所有主要的现代浏览器现在(在2019年)都支持此本机,但是,当然,像Internet Explorer这样的旧版浏览器不支持(甚至不支持IE11),因此,如果您需要定位旧版浏览器,则需要进行转换(例如,与类似Babel)。