【问题标题】:Understanding prototype/constructor in javascript [duplicate]了解javascript中的原型/构造函数[重复]
【发布时间】:2018-11-01 18:09:32
【问题描述】:
function A(){}

function B(){}

function C(){}

B.prototype = new A();
console.log(B.prototype.constructor);
C.prototype = new B();
console.log(C.prototype.constructor);

打印:

[功能:A]
[功能:A]

到目前为止,我的理解是,通常在 JavaScript 中,对象的构造函数属性是指创建它的构造函数。如果对象是由文字创建的,则构造函数属性引用该文字的基础类型。

鉴于上面 constructor 属性的“定义”,我不明白为什么它打印
[Function: A] 两次,而不是:

[功能:A]
[功能:B]

【问题讨论】:

  • 必须显式设置构造函数。 B.prototype = Object.create(A.prototype); B.prototype.constructor = B

标签: javascript constructor prototype


【解决方案1】:

当您设置prototype 时,您会清除前一个。并且,通过这样做,您在原型切换之前清除了对原始构造函数的引用(constructor 是存储在原型中的对象引用,如果您更改原型,您也会更改构造函数)。

当像这样手动进行继承时,您必须记住在交换原型后“修复”constructor 属性。您的代码没有这样做,因此当您调用new B() 时,您实际上是在使用A() 作为构造函数。然后,当您将C 的原型设置为new B() 时,A() 构造函数运行并返回A 的实例。

function A(){}

function B(){}

function C(){}

console.log("B.prototype.constructor before inheritance: ",  B.prototype.constructor);
B.prototype = new A();

C.prototype = new B();

console.log(A.prototype.constructor);  // A
console.log(B.prototype.constructor);  // A
console.log(C.prototype.constructor);  // A

console.log("B.prototype.constructor after inheritance: ",  B.prototype.constructor);



// We've completely changed the prototype (including the constructor), so we have to fix it:
B.prototype.constructor = B;
console.log("B.prototype.constructor after constructor fix: ",  B.prototype.constructor);

对于 JavaScript 类,我们通过在子类的构造函数中调用 super() 来解决这个问题,以确保正确调用父类的构造函数。这更紧密地模拟了在传统的基于类的编程语言中如何处理构造函数,但它只是一种语法糖抽象。来自MDN

class Animal { 
  constructor(name) {
    this.name = name;
  }
  
  speak() {
    console.log(this.name + ' makes a noise.');
  }
}

class Dog extends Animal {
  constructor(name) {
    super(name); // call the super class constructor and pass in the name parameter
  }

  speak() {
    console.log(this.name + ' barks.');
  }
}

var d = new Dog('Mitzie');
d.speak(); // Mitzie barks.

【讨论】:

  • “非手动”继承会让我们使用 class 关键字吗?你能举个简短的例子吗?
  • @Felix.C 完成了一个来自 MDN 的示例,该示例描述了 super() 如何处理类问题。
  • 谢谢你的例子。我认为我从这个问题和进一步阅读中得到的本质是只使用 ECMA6 类。但是还有一件事让我很困扰(gist.github.com/felixcra/a5c42217fc6404e44889ecc4da626eda) JavaScript 中的每个对象都有一些隐藏的属性,它指向它的构造函数在创建时所具有的原型对象?这也符合您所写的内容,因为在这种情况下,我完全理解为什么在我的原始示例中它会打印 [Function A] 两次。
  • @Felix.C 否。prototype“历史”不会保留在任何地方。而且,虽然 ES6 类混淆了架构,但重要的是要知道,从技术上讲,JavaScript 没有原生的内部类结构。它只是对象和原型。
  • 在您的示例中,它打印了两次A,因为您创建了B 的原型(以及构造函数,因为您从未更正它)A。所以,当你创建一个new B() 时,你实际上是在构造一个new A。而且,当您将C 的原型设置为new B() 时,您再次创建了一个新的A
猜你喜欢
  • 2017-08-21
  • 1970-01-01
  • 2015-08-09
  • 2020-05-23
  • 1970-01-01
  • 2014-08-20
  • 1970-01-01
  • 2015-04-20
  • 2012-04-04
相关资源
最近更新 更多