JS学习笔记-继承

继承的实现基于原型链

1、原型链继承

将父类的实例作为子类的原型son.prototype = new father()

//父类型
function Parent (){
this.name = "farther"
this.color = ["red"]
}
Parent.prototype.sayname=function (){
        return this.name}

function Son (){};
//继承 
Son.prototype = new Parent()
var son =new Son()

console.log(son.name) 
console.log(son.sayname())  //farther

var son2 =new Son();
son.color.push("blue")

console.log(son.color)    //["red","blue"]
console.log(son2.color)  //["red","blue"]  也变了
  • 缺点
    1、包含引用类型值的原型,会被所有实例共享
    2、没办法在不影响其他实例的情况下,给父类型构造函数传递参数,
    3、不能使用对象字面量创建原型方法,这样会重写原型。a.prototype={}

2、借用构造函数

在子类型的构造函数的内部调用超类型构造函数。

function Parent (){
    this.name = "farther"
    this.color = ["red"]
    }
Parent.prototype.sayname=function (){
        return this.name}


function Son(){
    Parent.call(this)}
 var son = new Son();
console.log(son.sayname())  //undefined访问不到
console.log(son.color)//["red"]
son.color.push("blue")
var son2 = new Son();
console.log(son.color)//["red","blue"]
console.log(son2.color)//["red"]  没有变

  • 优点:可以传递参数通过call/apply
  • 缺点:
    1、方法都在构造函数中定义,函数无法复用。
    2、原型中定义的属性方法对子类型是不可见的。sayname()是无法访问的。

3、组合继承

将原型链跟构造函数的技术组合到一块,发挥二者之长。

  • 使用原型链实现对原型属性和方法的继承,
  • 使用构造函数来实现对实例属性的继承。
//父类型
function Parent (){
    this.name = "farther"
    this.color = ["red"]
    }
Parent.prototype.sayname=function (){
        return this.name}
//子类型
function Son(){
    Parent.call(this)}   //继承属性
//继承方法
 Son.prototype = new Parent()
//实例
 var son = new Son();
 son.color.push("blue")
 console.log(son.color)   //["red","blue"]
 console.log(son.sayname()) //farther
 
 var son2 = new Son();
  console.log(son2.color)//["red"]
 console.log(son2.sayname()) //farther
 

避免了原型链和借用构造函数的缺陷,融合了他们的优点。成为js中最常用的继承模式。

  • 缺点:会调用两次超类型构造函数,一次是创建子类型构造函数时,一次是子类型构造函数内部。
  • 生成了两份实例(子类实例将子类原型上的那份屏蔽了)

4、原型式继承

5、寄生式继承

6、寄生组合继承

通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点

function a(a,b){
//创建对象
var c =function (){};
c.prototype = a.prototype;
//将实例作为子类的原型
b.prototype = new c ()
}
//父类型
function Parent (){
    this.name = "farther"
    this.color = ["red"]
    }
Parent.prototype.sayname=function (){
        return this.name}
        
function Son(){
    Parent.call(this)}   //继承属性
a(  Parent,Son);

var son = new Son();
 son.color.push("blue")
 console.log(son.color)   //["red","blue"]
 console.log(son.sayname()) //farther

通过一个立即执行函数作用域,在此作用域中创建一个临时类,临时类的原型 = 父类原型(解决构造函数继承中不能继承父类原型方法属性问题),
再将临时类的实例等于子类原型,因为是立即执行函数作用域,执行完就销毁了临时类的实例,也就避免了在组合继承里面保存了两份实例的问题。

7、使用ES6中的extends实现继承

//class 相当于es5中构造函数
//class中定义方法时,前后不能加function,全部定义在class的protopyte属性中
//class中定义的所有方法是不可枚举的
//class中只能定义方法,不能定义对象,变量等
//class和方法内默认都是严格模式
//es5中constructor为隐式属性


class Parent {
    constructor(name){
         this.name = "farther"
        this.color = ["red"]
    };
    sayname(){
        return this.name}
};

//继承父类
class Son extends Parent {
    constructor() {
        super();
    }
}

var son = new Son();
 son.color.push("blue")
 console.log(son.color)   //["red","blue"]
 console.log(son.sayname()) //farther
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值