返回

JavaScript 中为什么父类构造函数中的 this 是子类?

前端

在 JavaScript 中,子类继承父类时,子类的构造函数中的 this 指向子类实例,而不是父类实例。这是因为 JavaScript 的原型继承机制,子类通过继承父类的原型,获得了父类的属性和方法,但不共享父类的实例。

为什么父类构造函数中的 this 是子类?

JavaScript 中的 this 关键字指向当前执行上下文中的对象,而在构造函数中,this 指向新建的实例对象。当子类继承父类时,子类的构造函数会自动调用父类的构造函数,并在父类的构造函数中,this 指向父类的实例对象。然而,当父类的构造函数执行完毕后,this 又会指向子类的实例对象。

这是因为 JavaScript 的原型继承机制。在 JavaScript 中,每个对象都有一个原型对象,原型对象是该对象继承自父类(如果没有父类,则继承自 Object 对象)的属性和方法。当子类继承父类时,子类的原型对象指向父类的构造函数,这意味着子类继承了父类的原型对象中的所有属性和方法。

因此,当子类的构造函数调用父类的构造函数时,this 指向父类的实例对象,而在父类的构造函数执行完毕后,this 又会指向子类的实例对象。这是因为子类的实例对象继承了父类的原型对象,而 this 指向当前执行上下文中的对象,因此在父类的构造函数中,this 指向父类的实例对象,而在子类的构造函数中,this 指向子类的实例对象。

如何使用 this 来实现类继承?

在 JavaScript 中,可以使用 this 来实现类继承。具体做法是,在子类的构造函数中,使用 super() 调用父类的构造函数,然后在子类的构造函数中使用 this 来访问子类的属性和方法。

例如:

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

Parent.prototype.greet = function() {
  console.log('Hello, my name is ' + this.name);
};

function Child(name, age) {
  super(name);
  this.age = age;
}

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

Child.prototype.introduce = function() {
  console.log('Hello, my name is ' + this.name + ' and I am ' + this.age + ' years old.');
};

const child = new Child('John', 20);
child.greet(); // Hello, my name is John
child.introduce(); // Hello, my name is John and I am 20 years old.

在上面的例子中,Child 类继承了 Parent 类,并在 Child 类的构造函数中使用 super() 调用了 Parent 类的构造函数。然后在 Child 类的构造函数中使用 this 来访问 Child 类的属性和方法。在 Child 类的原型对象中,定义了一个 introduce() 方法,该方法使用 this 来访问 Child 类的属性和方法。

当创建一个 Child 类的实例对象时,首先会调用 Child 类的构造函数,然后在 Child 类的构造函数中调用 Parent 类的构造函数,并在 Parent 类的构造函数中使用 this 来访问 Parent 类的属性和方法。然后在 Child 类的构造函数中使用 this 来访问 Child 类的属性和方法。最后,创建 Child 类的实例对象。

当调用 Child 类的实例对象的 greet() 方法时,会调用 Parent 类的 greet() 方法,并在 Parent 类的 greet() 方法中使用 this 来访问 Parent 类的属性和方法。当调用 Child 类的实例对象的 introduce() 方法时,会调用 Child 类的 introduce() 方法,并在 Child 类的 introduce() 方法中使用 this 来访问 Child 类的属性和方法。