js中继承实现

304 阅读2分钟

在js语法中有原型这个特殊概念,继承大多也是围绕这个展开的

es5中

基本模式

通常在一个对象寻找方法和属性先会在这个方法的实例中寻找如果没有招到就会通过prototype属性去寻找一层层往上走,最后会找到Object对象所以在Object中的方法对象都会继承。

继承基本模式也就是将被继承对象写到继承对象的原型中

function father(){ 
    this.name = "father";
    this.say = function(){
        console.log('hi')
    }
};
function son(){  
    this.name = "son";
};
son.prototype = new father();//继承father
var sub = new son()//创建son实例
sub.say()//'hi'
sub.name//'son'

但将sub打印出来的时候发现没有prototype属性其实__proto__指向的是这个对象的构造函数的prototype。

打印name的时候发现name属性没有被继承其实是因为先在当前实例中寻找name属性找到了就不会往原型继续寻找了。

如果想要继承name可以用delete将name属性删除这样就会去向原型获取属性,如果只是将name的值设置成null是没有用的。

但这些继承方式都是引用类型,也会带来引用类型也带来的问题共享

借用构造函数

function father(){ 
    this.name = "father";
    this.say = function(){
        console.log('hi')
    }
};
function son(){  
    father.call(this);//继承father
    this.name = 'son'
};
var sub = new son();

sub.say()//'hi'
sub.name//'son'

这样子在实例中修改就不会影响其他实例因为继承的father是新创建的副本但这样又有一个新问题就是创造了过多的实例,这样就是没有复用这一说

组合继承

function father(){ 
    this.name = "father";
};
father.prototype.say =  function(){
    console.log('hi')
}
function son(){  
    father.call(this);//继承father属性
    this.name = 'son'
};
son.prototype = new father()//继承father方法
var sub = new son()//创建son实例

sub.say()//'hi'
sub.name//'son'

原型式继承

Object.creat()提供了另一种方法继承这个方法有两个参数一个是用做新原型(被继承)的对象和(可选)一个新对象定义额外属性对象。

当只有一个参数时和下列方法相同也就是创建了一个新对象将传入对象作为原型。

function object(o){
    function F(){}
    F.prototype = o;
    return new F();
}

第二个参数也就是填写需要增加的属性,如果属性与之前属性同名会将原来属性覆盖

es6

在es6新增了class关键字

构造函数可以写成

class son(){
    constructor() {
        name:'son'
    }
    say:function(){
        console.log('hi')
    }
}

其中name属性还是在实例中而方法会写在prototype创建实例方法和之前也一样var sub = new son()

继承可以写成

class father{
    constructor() {
        name:'father'
    }
    say(){
        console.log('hi')
    }
}
class son extends father{
    constructor() {
        super();
        name:'son';
    }
}

先写到这里有问题可以一起交流

邮箱:dcdawyx@163.com