js实现继承的几种方式

发布时间 2023-06-06 16:38:40作者: 写代码的马小跳

常见的实现继承的方式有以下几种:

1.原型链式继承

2.构造函数式继承

3.组合式继承

4.原型式继承

5.寄生式继承

6.寄生组合式继承

下面来详细讲些以下每种继承的实现方式,及优缺点

先声明一个叫Parent的构造函数  (引:JavaScript中的构造函数是一种特殊的函数,它用于创建新的对象实例)

function Parent() {
    this.name = 'parent1';
    this.play = [1, 2, 3];
    this.sayHei = function(){
        console.log("Hei~我是:" + this.name)
    }
  }
Parent.prototype.getFun = function(){
    console.log("你找到了这个方法!输出为:"+this.play)
}

 

一:原型链式继承

  实现方案:

function ChildOne() {
    this.type = 'childOne'; 
}
// 用.prototype 实现原型链式继承

ChildOne.prototype = new Parent(); 

var c1 = new ChildOne()

console.log(c1.name)
// 'parent1'

console.log(c1.play)
// [1, 2, 3]
console.log(c1.sayHei) // 'Hei~我是:parent1'
console.log(c1.getFun) // '你找到了这个方法!输出为:1,2,3'
 

缺点:

  1.原型中包含的引用值会在所有实例间共享  这是因为 在使用原型实现继承时,原型实际上变成了另一个类型的实例

var c2 = new ChildOne()

console.log(c2.play) // [1,2,3]

c2.play.push(4)

console.log(c2.play) // [1,2,3,4]

console.log(c1.play) // [1,2,3,4]
console.log(ChildOne.prototype.play) // [1,2,3,4]

// 由上可见,ChildOne原型上的play属性,都被改了

 

  2.子类型在实例化时不能给父类型的构造函数传参

 

二:构造函数式继承

  实现方案

function ChildTwo (){
// 借助call 来调用Parent函数
    Parent.call(this)
    this.type = 'child'
}
var t1 = new ChildTwo()
var t2 = new ChildTwo()

console.log(t1.name) // 'parent1'  

console.log(t1.play) // [1, 2, 3]

console.log(t1.sayHei) // 'Hei~我是:parent1'

t2.play.push(4)

console.log(t2.play) // [1,2,3,4]

console.log(t1.play) // [1,2,3]

 

缺点:

只能继承父类的实例属性和方法,不能访问父类原型上定义的方法

console.log(t1.getFun) // Uncaught TypeError: t1.getFun is not a function

console.log(t2.getFun) // Uncaught TypeError: t2.getFun is not a function

 

 

 

三:组合式继承 (把原型链式继承和构造函数式继承的优点结合。基本的思路是:使用原型链继承原型上的属性和方法,而通过盗用构造函数继承实例属性。)

 

 

实现方案:

function ChildThree() {
// 继承属性 Parent.call(
this) }
// 继承方法 ChildThree.prototype
= new Parent()

var s1 = new ChildTwo()
var s2 = new ChildTwo()

console.log(s1.name) // 'parent1'  

console.log(s1.play) // [1, 2, 3]

console.log(s1.sayHei) // 'Hei~我是:parent1'
console.log(s1.getFun) // '你找到了这个方法!输出为:1,2,3'
 s2.play.push(4)

console.log(s2.play) // [1,2,3,4]

console.log(s1.play) // [1,2,3]

完美的解决了上面的问题,唯一的缺点就是 Parent执行了两次【Parent.call(this) 和 new Parent()】,造成了多构造一次的性能开销