为什么当我“ console.log”对象时看不到从父对象继承的那些属性;为什么?在JavaScript中

时间:2019-08-26 19:17:28

标签: javascript inheritance

大家好,我最近正在学习JavaScript的继承。我创建了一个Child函数,并使其继承了Human函数。我先创建一个child的{​​{1}}实例,然后再创建Child

我想知道为什么输出仅具有console.log(child)属性,而没有Child属性。

我想这是因为属性描述符,特别是Human,但我无法弄清楚。谁能帮我吗?

enumerable

运行上述代码后,尽管const Child = function() { this.name = "child" } const Human = function() { this.move = "walking"; } Child.prototype = new Human(); Child.prototype.constructor = Child; const child = new Child(); console.log(child);给出了“行走”的信息,但我只看到{name:“ child”}。

1 个答案:

答案 0 :(得分:0)

简而言之,就是在move实例上找不到Child,但是在原型上它是从Human继承的。

让我们分析您的代码。

const Child = function() {
  this.name = "child"
}

const Human = function() {
  this.move = "walking";
}

这些是不言自明的,您创建了两个构造函数。它们无关(还)。

Child.prototype = new Human();
Child.prototype.constructor = Child;

这是继承部分。 Child.prototype = new Human();将创建Human的实例,并将其分配给Child.prototype,因为该实例具有成员move,该成员已分配给Child.prototype,而您得到本质上为Child.prototype = { move: 'walking' }Child.prototype.move = 'walking'的东西(虽然不准确,但足够接近)

然后,将Child本身分配为prototype.constructor


看到怪异行为的原因是您期望move是实例成员,但它是原型成员。这种影响的一个更严重的缺点是,更改child.move会同时对所有所有子实例进行更改,而这并不是您期望实例成员提供的。

由于这个原因,不建议像您一样通过实际创建实例来进行继承,而应像这样使用Object.create()

Child.prototype = Object.create(Human.prototype);
Child.prototype.constructor = Child;

此外,您的Child函数应调用父级构造函数,以维护父级的逻辑和成员。像这样:

const Child = function() {
  Human.call(this); // call to parent constructor
  this.name = "child";
}

完整代码:

const Human = function() {
  this.move = "walking";
}
const Child = function() {
  Human.call(this);
  this.name = "child"
}
Child.prototype = Object.create(Human.prototype);
Child.prototype.constructor = Child;

const child = new Child();
console.log(child);


一旦您了解了原型链的工作原理,请记住,创建了ES6类是为了更优雅,更易读的代码来处理这些情况:

class Human {
  constructor() {
    this.move = "walking";
  }
}

class Child extends Human {
  constructor() {
    super();
    this.name = "child";
  }
}