首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

js 继承 prototype

JavaScript 中的继承是通过原型链实现的,这是一种基于原型的面向对象编程模型。每个 JavaScript 对象都有一个指向其原型的内部链接,原型本身也是一个对象,这样就形成了一个链式结构,称为原型链。

基础概念

  • 原型(Prototype):每个函数都有一个 prototype 属性,这个属性指向一个对象,该对象包含可以被特定类型的所有实例共享的属性和方法。
  • 构造函数(Constructor):用于创建和初始化新对象的函数。通常,构造函数的名称以大写字母开头。
  • 实例(Instance):通过 new 关键字调用构造函数创建的对象。
  • 原型链(Prototype Chain):当访问对象的属性或方法时,JavaScript 引擎会首先在对象本身查找,如果没有找到,就会在其原型对象上查找,如果还没有找到,就会继续在原型的原型上查找,直到找到该属性或方法或到达原型链的末端(即 null)。

优势

  1. 代码复用:通过原型继承,可以将方法和属性添加到原型上,所有实例都可以共享这些方法和属性,节省内存。
  2. 灵活性:可以在运行时动态地向原型添加新的属性和方法,这些更改会立即反映到所有实例中。
  3. 易于扩展:可以创建子类并继承父类的属性和方法,同时还可以添加或覆盖父类的方法和属性。

类型

  1. 原型链继承:通过将子类的原型设置为父类的一个实例来实现继承。
  2. 构造函数继承:在子类构造函数中调用父类构造函数,并使用 callapply 方法来继承父类的属性。
  3. 组合继承:结合原型链继承和构造函数继承的优点,但存在一定的性能问题。
  4. 原型式继承:通过创建一个新对象,并将该对象的原型设置为另一个对象来实现继承。
  5. 寄生式继承:在原型式继承的基础上,增强对象,然后返回这个对象。
  6. 寄生组合式继承:被认为是实现继承的最佳方式,它结合了寄生式继承和组合继承的优点,避免了重复调用父类构造函数的问题。

应用场景

  • 创建具有相似属性和方法的对象:例如,创建一系列具有相同行为的 UI 组件。
  • 实现类库和框架:如 jQuery、React 等,它们利用继承来扩展功能。
  • 构建复杂的对象模型:在游戏开发或模拟系统中,对象之间可能存在复杂的层次关系。

示例代码

以下是一个简单的原型链继承示例:

代码语言:txt
复制
// 父类构造函数
function Animal(name) {
  this.name = name;
}

// 父类原型上的方法
Animal.prototype.sayName = function() {
  console.log('My name is ' + this.name);
};

// 子类构造函数
function Dog(name, breed) {
  // 调用父类构造函数,继承属性
  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);
};

// 创建子类实例
var myDog = new Dog('Buddy', 'Golden Retriever');

// 调用继承的方法
myDog.sayName(); // 输出: My name is Buddy
myDog.sayBreed(); // 输出: My breed is Golden Retriever

遇到的问题及解决方法

问题:原型链继承中,父类构造函数会被调用多次,导致性能问题。

原因:在组合继承中,子类的原型被设置为父类的一个新实例,这会调用父类构造函数一次。然后在子类构造函数中又会调用父类构造函数一次。

解决方法:使用寄生组合式继承,只调用一次父类构造函数。

代码语言:txt
复制
function inheritPrototype(subType, superType) {
  var prototype = Object.create(superType.prototype); // 创建对象
  prototype.constructor = subType; // 增强对象
  subType.prototype = prototype; // 指定对象
}

// 父类构造函数
function Animal(name) {
  this.name = name;
}

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

// 子类构造函数
function Dog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}

// 实现继承
inheritPrototype(Dog, Animal);

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

var myDog = new Dog('Buddy', 'Golden Retriever');
myDog.sayName();
myDog.sayBreed();

在这个例子中,inheritPrototype 函数帮助我们避免了重复调用父类构造函数的问题,从而提高了效率。

页面内容是否对你有帮助?
有帮助
没帮助

相关·内容

领券