js中的继承浅谈

js的继承主要是通过原型链来实现,有以下几种方式实现,各有优缺点。

第一种,原型式继承


function Top(){
    this.topName = 'top'
    this.roles = ['a']
}

Top.prototype.getTopName = function(){
    return this.name
}

function Down(){
    this.downName = 'down'
}

Down.prototype = new Top();
Down.prototype.getDownName = function (){
    return this.downName
}

let instance = new Down();
instance.roles.push('b')
let instanceTwo = new Down();
console.log(instance.getTopName()) // top
console.log(instace.roles) // ['a','b']
console.log(instaceTwo.roles) // ['a','b']

Dwon.prototype 不使用自己默认的原型,而是使用了new Top(),所以Down.prototype.[[Prototype]] === Top.prototype,Down可以使用Top的属性和方法,实现了继承。

优点:使用原型来进行继承,清楚明了;

缺点:当原型中包含引用值的时候,会在所有实例间共享;子类型在实例化时不能给父类型的构造函数传参。

第二种,盗用构造函数


function Top(name){
    this.name = name
    this.roles = ['a']
    this.doing = function(){
        return this.name
    }
}

Top.prototype.say = function(){
    console.log('111')
}

function Down(name){
    //继承Top
    Top.call(this,name)
}

let instance = new Down();
instance.roles.push('b');
let instanceTwo = new Down('down');
instance.doing() // undefined
instance.name //undefined
instance.say() // error

console.log(instanceTwo.name) // down
console.log(instanceTwo.roles) // ['a']
instanceTwo.doing() //down
instanceTwo.say() // error

优点:使用简单,解决了不能传参及引用值复用的问题。

缺点:必须在构造函数中定义方法,因此函数不能重复使用;子类型不能访问父类原型上的方法。

第三种,炮灰式继承


function paohui(o){
    function Demo(){}
    Demo.prototype = o
    return new Demo()
}
let person = {
    name:'a',
    friends:['jack','zo']
}

let anotherPerson = paohui(person);
anotherPerson.name = 'b'
anotherPerson.friends.push('rola');

let yetAnotherPerson = paohui(person);
yetAnotherPerson.friends.push('Linda');

console.log(person.friends) // 'jack,zo,rola,Linda'

这个paohui函数会创建一个临时构造函数,将传入的对象赋值给这个构造函数的原型,然后返回这个临时类型的一个实例。本质上,是对传入的对象执行了一次浅复制。

优点:适合不需要单独创建构造函数,但任然需要在对象间共享信息的场合。

缺点:和原型式继承一样,属性中包含的引用值始终会在相关对象间共享。

第四种,寄生式继承


function paohui(data){
     function Demo (){}
     Demo.prototype = data
     return new Demo()
}
function js(data){
   let clone = paohui(data)
   clone.say = function(){
      console.log(111)
   }
   return clone
}
let person = {
   name:'1',
   friends:[1]
}
let a = new js(person)
a.friends.push(2)
let b = new js(person)
console.log(b.friends) // '1,2'

优点:创建一个实现继承的函数,以某种方式增强对象。

缺点:和原型式继承一样,属性中包含的引用值始终会在相关对象间共享。

第五种,原型类组合继承


function Top(name){
    this.name = name;
    this.roles = ['Linda']
}

Top.prototpye.sayName = function (){
    console.log(this.name)
}

function Down(name,age){
    Top.call(this,name); // 第二次调用
    this.age = age;
}
Down.prototype = new Top(); // 第一次调用
Down.prototype.constructor = Down;
Down.prototype.sayAge = function(){
    console.log(this.age)
}

let instance = new Down('jack',20);
instance.roles.push('jack');

let instanceTwo = new Down('zo',18);
console.log(instanceTwo.roles) // 'Linda'

优点:解决了属性中的引用值共享的问题。

缺点:效率存在问题,父类的构造函数会被调用两次。

第六种,寄生组合式继承


function paohui(data){
     function Demo (){}
     Demo.prototype = data
     return new Demo()
}
function inheritPrototype(Top,Down){
    let prototype = paohui(Top);
    prototye.constructor = Down;
    Down.prototype = ptototype;
}
function Top(name){
    this.name = name;
    this.roles = ['Linda']
}

Top.prototpye.sayName = function (){
    console.log(this.name)
}

function Down(name,age){
    Top.call(this,name); 
    this.age = age;
}
inheritPrototype(Top,Down)

let instance = new Down('jack',20);
instance.roles.push('jack');
let instanceTwo = new Down('zo',18);
console.log(instanceTwo.roles)  // 'Linda'

优点:不仅解决了属性中引用值共享问题,而且Top构造函数只调用了一次,引用类型继承的最佳模式。

缺点:复杂程度相对高点

注:仅供个人学习记笔记使用,如果错误,欢迎指正👏🏻。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值