【问题标题】:2 ways to change a javascript object's prototype, what's the difference between them?2种更改javascript对象原型的方法,它们之间有什么区别?
【发布时间】:2016-08-17 03:09:52
【问题描述】:

我从stackoverflow中读到了这段代码,说明了如何在javascript中实现“继承”

var Base=function(){this.a='abc'};
var Sub = function () {};
Sub.prototype = new Base(); // note: this pattern is deprecated!
//Because we used 'new', the [[prototype]] property of Sub.prototype
//is now set to the object value of Base.prototype.
//The modern way to do this is with Object.create(), which was added in ECMAScript 5:
Sub.prototype = Object.create(Base.prototype);

我想知道,如果

Sub.prototype = new Base();

已弃用,采用新方式

Object.create(Base.prototype);

介绍正在创建的对象的任何内部差异?有什么内部属性差异,行为差异,所以我应该使用新的方式,并尝试将旧代码转换为新代码?

谢谢。

【问题讨论】:

  • 最大的不同是 Object.create 不会调用 Base 函数。它只是将该函数设置为原型并设置原型链。

标签: javascript object inheritance prototype


【解决方案1】:

恕我直言,做相关事情的现代方式是class 和相关关键字。

您建议的两个选项会产生不同的结果。见classical inheritance with Object.create。您缺少对超级构造函数的调用以及将 prototype.constructor 重新分配给正确的值(在另一种情况下也缺少)。

按照链接中的说明使用Object.create 进行继承时,与分配new Base() 相比的一个区别是可以找到属性的位置:

function Base() { this.baseProp = "baseProp"; }
function Sub() { this.subProp = "subProp"; }

Sub.prototype = new Base();
Sub.prototype.constructor = Sub;

let obj = new Sub();
console.log("obj.baseProp: " + obj.baseProp);
console.log("Has baseProp on itself: " + obj.hasOwnProperty("baseProp"));

function Base() { this.baseProp = "baseProp"; }
function Sub() {
  Base.call(this);
  this.subProp = "subProp";
}

//Note that here Base.prototype doesnt even have anything interesting
Sub.prototype = Object.create(Base.prototype);
Sub.prototype.constructor = Sub;

let obj = new Sub();
console.log("obj.baseProp: " + obj.baseProp);
console.log("Has baseProp on itself: " + obj.hasOwnProperty("baseProp"));

还要注意Object.create 仍然将额外的间接推送到原型链中(使用其他方法,包含Base 属性的对象将是)。但是,额外的步骤并不是“错误的”,而是可以看作是拆分 Sub 的原型属性和继承的原型属性(例如,如果您想在 Sub.prototype 中添加一些内容,那么您将很难做到这一点这种间接方式,因为您也会不小心添加到Base.prototype

function Base() { this.baseProp = "baseProp"; }
Base.prototype.someFunction = () => void 0;
function Sub() {
  Base.call(this);
  this.subProp = "subProp";
}

//Now this is important, the prototype contains something
Sub.prototype = Object.create(Base.prototype);
Sub.prototype.constructor = Sub;

let obj = new Sub();
console.log("First level link has function: " + obj.__proto__.hasOwnProperty("someFunction"));
console.log("Second level link has function: " + obj.__proto__.__proto__.hasOwnProperty("someFunction"));

【讨论】:

    【解决方案2】:

    我能指出的唯一区别是,当您使用new 时,Sub 的原型是Base实例。这意味着 所有属性 将在子类上可用(不仅仅是原型方法)。

    所以在你的例子中Sub.prototype = Object.create(Base.prototype); 什么都不继承。而Sub.prototype = new Base() 继承了a 属性

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-03-22
      • 2013-04-13
      • 2012-01-04
      • 2011-07-20
      • 2021-07-24
      • 1970-01-01
      • 2013-06-26
      相关资源
      最近更新 更多