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)。

10-05 20:58
查看更多