通过将__proto__放到原型中来继承JavaScript是不是很糟糕?

时间:2014-04-20 18:23:12

标签: javascript inheritance prototypal-inheritance

以下是从Child继承Parent的一种方式:

function Parent(a)
{
  this.a = a;
}

Parent.prototype =
{
  constructor: Parent,
  parentValue: 123
};

function Child(a, b)
{
  Parent.call(this, a);
  this.b = b;
}

Child.prototype =
{
  constructor: Child,
  childValue: 456,
  __proto__: Parent.prototype
};

child = new Child(1, 2);

// Logs 1 2 456 123
console.log(child.a, child.b, child.childValue, child.parentValue);

这种继承方式有缺点吗?

这背后的基本原理是我想批量添加属性,例如Foo.prototype = { a: 1, b: 2 }而非Foo.prototype.a = 1; Foo.prototype.b = 2;,因为后者过于冗长。

1 个答案:

答案 0 :(得分:2)

  

通过放置__proto__

来继承JavaScript是不是很糟糕

是的,因为它不是标准的(*)。更好地使用Object.create

function Parent(a) {
  this.a = a;
}
Parent.prototype.parentValue = 123;
function Child(a, b) {
  Parent.call(this, a);
  this.b = b;
}
Child.prototype = Object.create(Parent.prototype);
Child.prototype.constructor = Child;
Child.prototype.childValue = 456;
var child = new Child(1, 2);
console.log(child.a, child.b, child.childValue, child.parentValue);
    // Logs 1 2 456 123

或者,如果您想支持旧浏览器,则可以使用

代替Object.create
Child.prototype = new Parent();

请注意,此方法会导致Child个实例继承未定义的a属性,但由于您将使用Parent.call(this, a)创建自己的属性,因此无关紧要。


如果您想避免使用详细Foo.prototype.a = 1; Foo.prototype.b = 2;,可以使用extend函数:

function extend(obj, props) {
    for(var i in props) if(props.hasOwnProperty(i))
        obj[i] = props[i];
}
extend(Child.prototype, {
    constructor: Child,
    childValue: 456
});

(*)ES6在(规范)附件中包含__proto__,用于Web浏览器的附加ECMAScript功能(请注意,该规范对已实现的内容进行了编码),但如果ECMAScript主机不是网页浏览器。 但MDN表示__proto__已被弃用。

或者,ES6引入Object.setPrototypeOf(),允许更改原型__proto__,但MDN警告:

  

使用此方法或更改对象的[[Prototype]]   强烈建议不要使用已弃用的Object.prototype.__proto__,   因为它很慢并且随后不可避免地减慢速度   在现代JavaScript实现中执行。