Object.create与直接原型继承

bea*_*mit 9 javascript prototypal-inheritance ecmascript-5 object-create

我一直在使用EcmaScript 5规范中的Object.create,我正在尝试创建一个多继承类型结构.

假设我有一些功能:a,b和c.只处理原型,我可以这样做:

function a () {}
a.prototype = {
    fnA = function () {},
    propA = 500
};

function b () {}
b.prototype = a.prototype;
b.prototype.fnB = function () {};
b.prototype.propB = 300;

function c () {}
c.prototype = b.prototype;
c.prototype.fnC = function () {};
c.prototype.propC = 200;
Run Code Online (Sandbox Code Playgroud)

但是使用Object.create,我会做一些事情:

function a() {}
a.prototype = {
    fnA = function () {},
    propA = 500
};

var b = Object.create(new a());
b.fnB = function () {};
b.propB = 300;

var c = Object.create(b);
c.fnC = function () {};
c.propC = 200;
Run Code Online (Sandbox Code Playgroud)

我想我从两个方面都得到了同样的结果.

这看起来有点笨重,因为我得到了对象而不是构造函数.在我看来,进行常规原型继承不那么具有侵入性,对于不需要任何特殊处理的模块化应用程序更有意义.

我错过了什么吗?尝试使用构造函数创建Object.create有什么好处吗?或者这仅用于复制现有对象?我只想访问附加到原型的属性和函数,而不是之后添加到对象的函数和属性.

或者这个(或者使用更好的深层拷贝,但想法保持不变)?

function A () {}
A.prototype = {
    fn: function () {
        console.log(this.propA + 30);
    },
    propA: 20
};

function B () {}
Object.keys(A.prototype).forEach(function (item) {
    B.prototype[item] = A.prototype[item];
});
B.prototype.propA = 40;

function C () {}
Object.keys(B.prototype).forEach(function (item) {
    C.prototype[item] = B.prototype[item];
});
C.prototype.fn = function () {
    console.log(this.propA + 3);
};


var a = new A(),
    b = new B(),
    c = new C();

a.fn();
b.fn();
c.fn();
Run Code Online (Sandbox Code Playgroud)

jmb*_*all 4

实际上,两种方法都不会得到相同的结果。考虑这一行:

b.prototype = a.prototype;
Run Code Online (Sandbox Code Playgroud)

它所做的就是设置b.prototype与 完全相同的对象引用a.prototype。如果您更改第一个对象(例如通过添加fnB方法),您也会更改第二个对象。他们是一样的东西。在第一组代码结束时,您将拥有三个完全相同的原型,具有相同的方法和属性。

原型继承的全部要点是,您定义一个“有趣的”对象(即,具有您想要的所有行为),然后使用 Object.create 克隆它并修改克隆以满足您的需要(通常通过修改其属性,而不是修改它的属性)。它的方法)。

所以假设你有一个加法器对象:

var adder = {x: 0, y: 0};
adder.execute = function () {
  return this.x + this.y;
}
Run Code Online (Sandbox Code Playgroud)

然后创建一个克隆并设置其属性:

var myadder = Object.create(adder);
myadder.x = 1;
myadder.y = 2;
console.log(myadder.execute()); // 3
Run Code Online (Sandbox Code Playgroud)

显然,这是一个愚蠢的示例,但它表明您可以考虑原型继承,而不必在这些构造函数上编写构造函数和显式原型。

  • `execute()` 会抛出 **ReferenceError**,除非您将其更改为 `return this.x + this.y;` (4认同)
  • 最好使用“Object.create”。因此, `b.prototype = Object.create(a.prototype);` 然后我们使用更好的解决方案使较小的解决方案变得更好。 (2认同)