【问题标题】:Javascript call Parent constructor in the Child (prototypical inheritance) - How it works?Javascript 在 Child 中调用 Parent 构造函数(原型继承) - 它是如何工作的?
【发布时间】:2015-01-17 00:59:36
【问题描述】:

我知道它有效,但我不知道为什么以及如何。机制是什么?

// Parent constructor
function Parent(name){
  this.name = name || "The name property is empty";
}

// Child constructor
function Child(name){
  this.name = name;
}

// Originaly, the Child "inherit" everything from the Parent, also the name property, but in this case
// I shadowing that with the name property in the Child constructor.
Child.prototype = new Parent();

// I want to this: if I dont set a name, please inherit "The name property is empty" from the 
// Parent constructor. But I know, it doesn't work because I shadow it in the Child.
var child1 = new Child("Laura");
var child2 = new Child();

//And the result is undefined (of course) 
console.log(child1.name, child2.name);  //"Laura", undefined

我知道我需要什么,call()apply() 方法。从Child 调用“超类”(Parent 构造函数),并将this 对象和参数name 传递给它。它有效:

function Parent(name){
  this.name = name || "The name property is empty";
}

function Child(name){
  // Call the "super class" but WHAT AM I DO? How does it work? I don't understand the process, I lost the line.
  Parent.call(this, name);
}

Child.prototype = new Parent();

var child1 = new Child("Laura");
var child2 = new Child();

console.log(child1.name, child2.name); // "Laura", "The name property is empty"

效果很好,但我不明白会发生什么。脑子里把this丢了,跟不上call()方法的流程。这会将构造函数主体从Parent 复制到Child 还是什么? this 对象在哪里?为什么会起作用?

请帮忙描述一下过程,我不明白。

【问题讨论】:

标签: javascript constructor prototype call chain


【解决方案1】:

首先,停止使用Child.prototype = new Parent(); 进行继承,除非您的浏览器不支持任何其他替代方案。这是一种非常糟糕的风格,并且可能会产生不良副作用,因为它实际上运行的是构造函数逻辑。

您现在可以在每个现代浏览器中使用Object.create

Child.prototype = Object.create(Parent.prototype);

请注意,在此之后您还应该修复Child.prototypeconstructor 属性,使其正确指向Child 而不是Parent

Child.prototype.constructor = Child;

接下来,call 是如何工作的?那么call 允许指定在函数执行时this 关键字将引用哪个对象。

function Child(name){
  //When calling new Child(...), 'this' references the newly created 'Child' instance

  //We then apply the 'Parent' constructor logic to 'this', by calling the 'Parent' function
  //using 'call', which allow us to specify the object that 'this' should reference 
  //during the function execution.
  Parent.call(this, name);
}

【讨论】:

  • 这种技术被称为“构造函数窃取”
  • 为了展示 OP 对 w/r/t 原型继承感到好奇的 this/constructor/call 的完整机制,我会确保添加“Child.prototype.constructor = Child;”在“Child.prototype = Object.create(Parent.prototype)”行之后。除非你这样做,否则 Child.prototype.constructor 将等于 Parent.prototype.constructor,这将导致一些意想不到的后果——尤其是。如果您开始添加特定于 Child 构造函数的参数和/或初始化功能。 OP 没有明确询问这种情况,但强调一下很有用..
  • 我知道这一点,我通常会修复构造函数成员,但认为它超出了答案的范围。不过,这可能还是值得一提的。
  • @plalx 如果您正在构建一个必须满足 IE8 的网站,那么您别无选择,只能使用“糟糕的风格”。投票否决,因为该解决方案没有提供具有 OP 技术的解决方案。
  • @plalx,“不良副作用”的例子是什么?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-08
  • 2014-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多