JS中的继承实现

一.类式继承

//父类
function superClass(value){
    this.superValue = value;
}
superClass.prototype.getSuperValue = function(){
    return this.superValue;
}

//子类
function subClass(value){
    this.subValue = value;
}

//子类继承父类
subClass.prototype = new superClass('super');
subClass.prototype.getSubValue = function(){
    return this.subValue;
}

var instance = new subClass('sub');
console.log(instance.getSuperValue());//super
类式继承有两个明显的缺点:

1.父类中的公有属性要是引用类型,就会在子类中被所有实例共用,如果其中一个子类实例更改了父类的公有属性则会引响到其他实例。

2.在实例化子类的时候无法通过传参来对弗雷构造函数内的属性进行初始化。


二.构造函数继承

// 构造函数继承
function superClass(id){
    this.books = ['html', 'css', 'js'];
    this.id = id;
}
superClass.prototype.showBooks = function(){
    console.log(this.books);
}

function subClass(id){
    superClass.call(this, id);
}
var instance1 = new subClass(100);
var instance2 = new subClass(200);
instance1.books.push('php');
console.log(instance1.books);//[ 'html', 'css', 'js', 'php' ]
console.log(instance2.books);//[ 'html', 'css', 'js']
console.log(instance1.showBooks);//undefined
可以看到,构造函数继承是在子类构造函数中调用父类构造函数,这样解决了类式继承中出现的两个问题,但同时又增加了一个新的问题那就是子类实例无法共享父类原型中的属性和方法。如果想要继承必须放在父类构造函数中,这样会造成大量的内存浪费,不符合代码复用原则。


三.组合继承

function superClass(id){
    this.books = ['html', 'css', 'js'];
    this.id = id;
}
superClass.prototype.showBooks = function(){
    console.log(this.books);
}
function subClass(id, name){
    superClass.call(this, id);
    this.name = name;
}
subClass.prototype = new superClass();

var instance1 = new subClass(100, 'jack');
var instance2 = new subClass(200, 'tom');
instance1.books.push('php');
console.log(instance1.books);// ['html', 'css', 'js', 'php']
console.log(instance2.books);// ['html', 'css', 'js']
console.log(instance1.showBooks());// ['html', 'css', 'js', 'php']

可以看到组合继承是结合了类式继承和构造函数继承的优点,但还是存在一点小瑕疵那就是父类构造函数被执行了两遍,这多少让人觉得有点不太舒服。


四.原型式继承

function inheritObject(o){
    // 声明一个过渡对象
    function F(){};
    F.prototype = o;
    return new F();
}

这其实就是对于类式继承的一个封装,也是Object.create()方法的原型,当然类式继承中存在的问题这里依然会存在。


五.寄生式继承

function createBook(obj){
    var o = new inheritObject(obj);
    o.getName = function(){
        console.log(name);
    }
    return o;
}
寄生式继承其实就是对原型式继承的二次封装,在二次封装的过程中对新对象进行扩展。


六.寄生组合式继承

function inheritPrototype(subClass, superClass){
    var p = inheritObject(superClass.prototype);
    p.constructor = subClass;
    subClass.prototype = p;
}
function superClass(id){
    this.books = ['html', 'css', 'js'];
    this.id = id;
}
superClass.prototype.showBooks = function(){
    console.log(this.books);
}
function subClass(id, name){
    superClass.call(this, id);
    this.name = name;
}
inheritPrototype(subClass, superClass);
var instance1 = new subClass(100, 'jack');
var instance2 = new subClass(200, 'tom');
instance1.books.push('php');
console.log(instance1.books);//['html', 'css', 'js', 'php']
console.log(instance2.books);//['html', 'css', 'js']
console.log(instance1.showBooks());//['html', 'css', 'js', 'php']

寄生组合式继承是一种近乎完美的继承方式,需要注意的是在子类原型上添加方法的时候不能直接给prototype对象赋值对象






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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值