文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

JavaScript中常见的七种继承及实现

2023-03-08 08:04

关注

1. 原型链继承

原型链继承是 JavaScript 中一种基于原型的继承方式,它通过将一个构造函数的实例作为另一个构造函数的原型,从而实现继承。具体来说,就是在子类的构造函数中通过 Child.prototype = new Parent() 的方式来继承父类的属性和方法。

以下是一个实现原型链继承的示例代码:

// 定义父类构造函数functionParent(name) {
  this.name = name;
}
 
// 父类原型上的方法Parent.prototype.sayName = function() {
  console.log('My name is ' + this.name);
}
 
// 定义子类构造函数functionChild(name, age) {
  this.age = age;
}
 
// 将子类的原型设置为父类的实例Child.prototype = newParent();
 
// 子类原型上的方法Child.prototype.sayAge = function() {
  console.log('I am ' + this.age + ' years old');
}
 
// 创建子类实例var child = newChild('Tom', 10);
 
// 调用子类实例的方法
child.sayName(); // My name is Tom
child.sayAge(); // I am 10 years old复制代码

在上面的示例代码中,我们首先定义了一个父类构造函数 Parent,并在其原型上定义了一个方法 sayName。然后我们定义了一个子类构造函数 Child,并通过将子类的原型设置为父类的实例来实现继承。最后我们创建了一个子类实例 child,并调用其方法来验证继承是否成功。

优点:

缺点:

2. 借用构造函数继承

JavaScript中的借用构造函数继承是一种通过调用父类构造函数来实现继承的方式。这种继承方式有以下特点:

子类实例拥有了父类构造函数中定义的属性和方法。

子类实例与父类实例之间不存在原型链的关系,因此可以避免共享原型对象带来的问题。

子类无法重用父类原型对象上的方法。

以下是一个借用构造函数继承的示例代码:

functionAnimal(name) {
  this.name = name;
}
 
Animal.prototype.sayName = function() {
  console.log('My name is ' + this.name);
}
 
functionDog(name, age) {
  Animal.call(this, name); // 借用Animal构造函数,并将this指向Dog实例this.age = age;
}
 
let dog1 = newDog('旺财', 2);
let dog2 = newDog('小白', 1);
 
console.log(dog1.name); // '旺财'console.log(dog2.age); // 1
dog1.sayName(); // TypeError: dog1.sayName is not a function复制代码

在上面的代码中,Dog类通过调用Animal构造函数来实现继承,从而拥有了Animal类中定义的属性和方法。由于子类实例与父类实例之间不存在原型链的关系,因此修改一个实例的属性不会影响到其他实例。

但是需要注意的是,由于子类实例无法访问父类原型对象上的方法,因此在上面的代码中,dog1实例调用sayName()方法会报错。如果需要在子类中重用父类原型对象上的方法,可以考虑使用组合继承或寄生组合式继承。

优点:

缺点:

3. 组合继承

JavaScript中的组合继承是一种结合借用构造函数和原型链继承的方式,它的核心思想是使用借用构造函数继承实例属性和方法,使用原型链继承共享属性和方法。

以下是一个组合继承的示例代码:

functionAnimal(name) {
  this.name = name;
}
 
Animal.prototype.sayName = function() {
  console.log('My name is ' + this.name);
}
 
functionDog(name, age) {
  Animal.call(this, name); // 借用Animal构造函数,并将this指向Dog实例this.age = age;
}
 
Dog.prototype = newAnimal(); // 原型链继承Animal类的属性和方法Dog.prototype.constructor = Dog; // 修复构造函数指向let dog1 = newDog('旺财', 2);
let dog2 = newDog('小白', 1);
 
console.log(dog1.name); // '旺财'console.log(dog2.age); // 1
dog1.sayName(); // 'My name is 旺财'复制代码

在上面的代码中,Dog类通过借用Animal构造函数继承实例属性和方法,通过原型链继承Animal类的属性和方法。由于子类实例与父类实例之间不存在原型链的关系,因此修改一个实例的属性不会影响到其他实例。同时,子类实例可以重用父类原型对象上的方法。

需要注意的是,由于在上面的代码中通过Dog.prototype = new Animal()创建了一个新的Animal实例,因此在创建Dog类时会调用两次Animal构造函数,造成了性能上的浪费。可以使用寄生组合式继承来解决这个问题。

具体来说,组合继承通过将父类的构造函数借用到子类中,从而实现了父类属性的继承,同时通过将子类的原型设置为一个新的父类实例,从而实现了父类方法的继承。这种继承方式具有以下优缺点:

优点:

缺点:

4. 原型式继承

JavaScript中的原型式继承是一种基于已有对象创建新对象的继承方式,它利用了对象的动态特性,通过封装一个函数来实现继承。该函数接收一个用作新对象原型的对象作为参数,并返回一个新对象,从而实现了继承。该方式与借用构造函数继承类似,但它并不涉及到构造函数和实例的概念。原型式继承具有以下特点:

基于已有对象创建新对象。

可以使用Object.create()方法实现。

可以将一个对象作为另一个对象的原型对象。

可以使用原型对象的属性和方法,但不会影响到原型对象本身。

下面是一个使用原型式继承的示例代码:

let animal = {
  type: 'animal',
  sayType: function() {
    console.log('I am a ' + this.type);
  }
};
 
let dog = Object.create(animal); // 使用animal对象作为dog对象的原型
dog.type = 'dog';
 
dog.sayType(); // 'I am a dog'复制代码

在上面的代码中,animal对象拥有一个type属性和一个sayType方法,dog对象通过使用animal对象作为原型对象来实现了继承。因此,dog对象可以使用原型对象的属性和方法,但并不会影响到原型对象本身。此外,通过给dog对象添加一个type属性,也可以覆盖原型对象的type属性,实现对父对象属性的重写。原型式继承的优点在于可以方便地实现对象的复用,但也容易导致对象之间的耦合,不易于维护。

具体来说,它通过创建一个空对象,并将其原型设置为一个已有对象,然后向这个空对象中添加属性和方法来实现继承。原型式继承具有以下优缺点:

优点:

缺点:

5. 寄生式继承

JavaScript中的寄生式继承是一种基于已有对象创建新对象的继承方式,类似于原型式继承。它的主要区别是,在新创建的对象上增加一个方法,而这个方法的作用是以某种方式增强对象,然后返回这个对象。这种继承方式得名于“寄生”,因为增强对象的方法通常是基于已有的对象进行“寄生”而得名。

寄生式继承的优点是可以封装继承过程,并且可以向对象中添加一些额外的属性和方法。但是和原型式继承一样,也存在父对象的引用属性被所有子对象共享、无法判断实例是否是父对象的实例等问题。

以下是一个使用寄生式继承的示例代码:

functioncreateAnimal(type) {
  let animal = {
    type: type,
    sayType: function() {
      console.log('I am a ' + this.type);
    }
  };
  // 基于animal对象进行寄生增强let dog = Object.create(animal);
  dog.bark = function() {
    console.log('woof woof');
  };
  return dog;
}
 
let myDog = createAnimal('canine');
myDog.sayType(); // 'I am a canine'
myDog.bark(); // 'woof woof'复制代码

在上面的代码中,我们定义了一个名为createAnimal的函数,用于创建一个继承自animal对象的新对象。我们在这个新对象上增加了一个bark方法,用于让对象发出叫声。最后,我们返回这个新对象,并将它赋值给myDog变量。通过这样的方式,我们成功地实现了寄生式继承。

具体来说,它在原型式继承的基础上增加了一个包装函数,该函数用于封装继承过程中的一些增强行为。寄生式继承具有以下优缺点:

优点:

缺点:

6. 寄生式组合继承

JavaScript中的寄生式组合继承是一种结合了组合继承和寄生式继承的继承方式。具体来说,它在组合继承的基础上,通过寄生式继承来解决组合继承中重复调用父构造函数的问题。

下面是一个使用寄生式组合继承的示例代码:

functionAnimal(name) {
  this.name = name;
  this.type = 'mammal';
}
 
Animal.prototype.sayName = function() {
  console.log('My name is ' + this.name);
};
 
functionDog(name, breed) {
  Animal.call(this, name);
  this.breed = breed;
}
 
// 使用寄生式继承继承Animal.prototypeDog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
 
Dog.prototype.sayBreed = function() {
  console.log('I am a ' + this.breed);
};
 
let myDog = newDog('Max', 'Golden Retriever');
myDog.sayName(); // 'My name is Max'
myDog.sayBreed(); // 'I am a Golden Retriever'复制代码

在上面的代码中,我们定义了Animal和Dog两个构造函数,其中Animal构造函数定义了一个name属性和一个sayName()方法,Dog构造函数在Animal的基础上添加了一个breed属性和一个sayBreed()方法。为了实现寄生式组合继承,我们使用Object.create()方法基于Animal.prototype创建了一个新的对象,并将其赋值给Dog.prototype,从而使得Dog.prototype的原型链指向了Animal.prototype。同时,我们还将Dog.prototype的constructor属性设置为Dog,以保证继承链的完整性。最后,我们通过调用Animal构造函数并将this指向Dog对象,实现了对Animal属性的继承。通过这种方式,我们既避免了组合继承中重复调用父构造函数的问题,又保留了寄生式继承的灵活性,实现了一个高效而且灵活的继承方式。

优点:

缺点:

7. class继承

在ES6及以上的版本中,JavaScript引入了class关键字,用于定义类,从而实现面向对象编程。class继承是一种通过类来实现继承的方式,它使用extends关键字来指定父类,并通过super关键字来调用父类的构造函数和方法。

以下是一个使用class继承的示例代码:

classAnimal {
  constructor(type) {
    this.type = type;
  }
 
  sayType() {
    console.log('I am a ' + this.type);
  }
}
 
classDogextendsAnimal {
  constructor(type, name) {
    super(type);
    this.name = name;
  }
 
  sayName() {
    console.log('My name is ' + this.name);
  }
}
 
let dog = newDog('canine', 'Fido'); // 创建一个新的Dog对象
 
dog.sayType(); // 'I am a canine'
dog.sayName(); // 'My name is Fido'复制代码

在上面的代码中,我们首先定义了一个Animal类,它包含一个构造函数和一个sayType()方法。然后我们通过extends关键字来指定Dog类的父类为Animal,并在Dog类的构造函数中通过super关键字来调用Animal构造函数,并实现了sayName()方法。最后,我们创建一个新的Dog对象,并调用它的方法来测试继承是否成功。

优点:

缺点:

总体来说,class继承是一种非常方便的继承方式,特别是在面向对象编程中,能够大大简化代码的编写和维护。但在一些特定情况下,其他继承方式可能更为适合。

以上就是JavaScript中常见的七种继承及实现的详细内容,更多关于JavaScript继承的资料请关注编程网其它相关文章!

阅读原文内容投诉

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

软考中级精品资料免费领

  • 历年真题答案解析
  • 备考技巧名师总结
  • 高频考点精准押题
  • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

    难度     813人已做
    查看
  • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

    难度     354人已做
    查看
  • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

    难度     318人已做
    查看
  • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

    难度     435人已做
    查看
  • 2024年上半年系统架构设计师考试综合知识真题

    难度     224人已做
    查看

相关文章

发现更多好内容

猜你喜欢

AI推送时光机
位置:首页-资讯-前端开发
咦!没有更多了?去看看其它编程学习网 内容吧
首页课程
资料下载
问答资讯