# javascript 继承

我们知道js是弱类型,半面向对象语言,在实现继承时并没有那些面向对象语言那样方便 下面我们总结几种js实现继承的方法,并总结他们的优缺点。

# 原型赋值发


function Per(name){
    this.name = name || '码不停息'}
Per.prototype.say = function(){
    console.log(this.name)
}

function Sun(){}
Sun.prototype = new Per();
const sun = new Sun();
console.log(sun.name) // 码不停息

这种方法是直接new 了一个父类的实例,然后赋给子类的原型。这样也就相当于直接将父类原型中的方法属性以及挂在this上的各种方法属性全赋给了子类的原型,简单粗暴!

因为简单粗暴,所以弊端很多

  1. new实例的时候不能给父类传参数

如上个例子所示,Sun 函数里面什么都没有,我们new的时候还怎么传参数,即使Sun函数体里面有值,他也不能和Per函数建立联系

  1. 自己的prototype被占用

为了继承父类的实例直接赋值给了Sun.prototype,那Sun还怎么用自己的prototype

# 调用构造函数方式

function Per(name){
    this.name = name || '码不停息'}
Per.prototype.say = function(){
    console.log(this.name)
}
function Sun(){
    Per.apply(this.arguments)
}
const sun = new Sun();
console.log(sun.name) // 码不停息
sun.say()  // sun.say is not a function

在子类的在构造函数里用子类实例的this去调用父类的构造函数(改变this指向),从而达到继承父类属性的效果

但是这种方法却不能继承父类的prototype,所有sun调用不到say方法

# 组合继承

上面两种方法各有缺点,那能不能互补一下呢?

function Per(name){
    this.name = name || '码不停息'}
Per.prototype.say = function(){
    console.log(this.name)
}
function Sun(){
    Per.apply(this.arguments)
}
Sun.prototype = new Per();

const sun = new Sun();
console.log(sun.name) // 码不停息
sun.say();  // 码不停息

看似很完美,父类的属性和方法都可以访问到,还可以给父类传递参数

栈例子

这是什么情况? name即出现了sun里面也出现了sun的__proto__里面。

看来组合方式把两种方式都有的也叠加了一切,实在是太不优雅

# 寄生组合继承

这是目前es5中主流的继承方式

function Per(name){
    this.name = name || '码不停息'}
Per.prototype.say = function(){
    console.log(this.name)
}
function Sun(){
    Per.apply(this.arguments)
}

Sun.prototype = Object.create(Pre.prototype);
const sun = new Sun();
console.log(sun.name) // 码不停息
sun.say();  // 码不停息

这里用到了Object.creat(obj)方法,该方法会对传入的obj对象进行浅拷贝。和上面组合继承的主要区别就是:将父类的原型复制给了子类原型。这种做法很清晰

但是也有一点小小弊端就是Per和Sun的constructor都指向了Pre,大部分情况下使用这种继承方式没问题,但是如果要使用constructor的话, 我们要加上这样一句话 Sun.prototype.constructor = Sun 可以说,ES6之前实现继承确实不是一件容易的事,特别和强类型语言对比来说,Javascript实现继承只能用'另类'来说

但是现在,我们可以说Javascript站起啦!

# ES6实现继承

class Per{
    constructor(name){
        this.name = name || '码不停息';
    }
    say(){
        console.log(this.name)
    }
}

class Sun extends Per {
    constructor(name){
        super(name);
        this.age = 16;
    }
}
const sun = new Sun('lyh');
console.log(sun) //{name: "lyh" , age: 16}


只能用两个字来形容 优雅