JavaScript中使用call、apply、bind实现原型继承

41 阅读2分钟

注意: 当你使用callapply方法时,你实际上是在创建一个新的上下文(this)。因此,你需要特别注意this的指向,以确保你的代码能够按预期工作。

使用call或apply实现原型继承

在JavaScript中,我们可以使用callapply方法来在子类的构造函数中调用父类的构造函数,从而实现继承。例如:

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

Animal.prototype.sayName = function() {
  console.log(`My name is ${this.name}`);
};

function Dog(name, breed) {
  // 使用call方法在子类的构造函数中调用父类的构造函数
  Animal.call(this, name);
  
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.sayBreed = function() {
  console.log(`My breed is ${this.breed}`);
};

let dog = new Dog('Fido', 'German Shepherd');

dog.sayName(); // 输出:My name is Fido
dog.sayBreed(); // 输出:My breed is German Shepherd

在以上的例子中,我们使用Animal.call(this, name)Dog的构造函数中调用了Animal的构造函数,这使得Dog能够继承Animal的属性。我们也可以使用apply方法达到同样的效果。

使用apply实现原型继承

apply的使用场景和call相似,不同的是,apply可以将一个数组或者类数组的对象作为函数的参数。这在你需要继承父类且父类构造函数接受数组参数时,非常有用。看下面的例子:

function Animal(names) { // 注意这里接收的是一个数组
  this.names = names;
}

Animal.prototype.sayNames = function() {
  console.log(`My names are ${this.names.join(", ")}`);
};

function Dog(names, breed) {
  // 使用apply方法在子类的构造函数中调用父类的构造函数
  Animal.apply(this, [names]);
  
  this.breed = breed;
}

Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;

Dog.prototype.sayBreed = function() {
  console.log(`My breed is ${this.breed}`);
};

let dog = new Dog(['Fido', 'Buddy'], 'German Shepherd');

dog.sayNames(); // 输出:My names are Fido, Buddy
dog.sayBreed(); // 输出:My breed is German Shepherd

在这个例子中,我们使用Animal.apply(this, [names])Dog的构造函数中调用了Animal的构造函数,这使得Dog能够继承Animal的属性。注意我们将names参数作为一个数组传递,这是apply方法的特性。

使用bind实现原型继承

虽然bind方法不常用于实现原型继承,但在某些情况下,你可能会发现它非常有用。例如,你可能需要在某个函数中固定this的值,而这个函数可能是从原型链上继承来的。例如:

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

Animal.prototype.sayName = function() {
  console.log(`My name is ${this.name}`);
};

let dog = {
  name: 'Fido',
  sayName: Animal.prototype.sayName.bind(this)
};

dog.sayName(); // 输出:My name is Fido

在以上的例子中,我们使用Animal.prototype.sayName.bind(this)创建了一个新的函数,并将这个函数赋值给了dog.sayName。这使得无论dog.sayName在何处被调用,它的this值都会被绑定到dog