【前端】JavaScript继承实现的四种方式

转载请注明出处:http://www.cnblogs.com/shamoyuu/p/4770235.htmlhtml

1、继承的实现方法

一、原型链继承

这个继承最为简单,它的实现原理是,每个AO对象都有一个prototype,返回对象类型原型的引用,因此能够给它赋值一个对象,就能够实现简单的原型链继承。app

function Animal(){
    this.eat = function(){
        alert("我会吃");
    }
}

function Bird(){
    this.fly = function(){
        alert("我会飞");
    }
}
//设置Bird类的原型为一个Animal对象
Bird.prototype = new Animal();

var pigeon = new Bird();
pigeon.fly();
pigeon.eat();

结果出现了,实现了鸟类继承动物会吃的特性。打印一下console.info(pigeon)咱们能够看到:函数

当前对象的__proto__属性为一个Animal对象,而eat方法在这个Animal对象也就是它的父类里,若是一个属性或方法在当前对象里没法找到的话,就会照着原型链一步一步找上去。this

这里Bird的父类是Animal,Animal的父类是Object,或者说全部没有直接指定prototype的对象,它的父类都是Object。由于toString()方法就是在Object里,因此全部对象均可以调用它。而Object的父类是null。spa

还有一个须要注意的问题是,原型链继承中,全部的子类的父类对象都是同一个。只要任意一个子类改变了父类对象的属性,那全部对象都会受到影响。这点多是缺点,也多是优势。prototype

注:prototype和__proto__的区别能够看我另一篇博客 http://www.cnblogs.com/shamoyuu/p/prototype.html3d

二、原型冒充继承

原型冒充的原理是:把父类的构造函数拿过来执行一遍。下面看代码:code

function Animal(){
    this.eat = function(){
        alert("我会吃");
    }
}

function Bird(){
    Animal.apply(this, arguments);this.fly = function(){
        alert("我会飞");
    }
}

var pigeon = new Bird();
pigeon.fly();
pigeon.eat();

效果跟上面是同样同样的,可是这个时候eat方法已经不在原型链上,而是在pigeon对象上。htm

三、复制继承

复制继承的原理是:把父类全部的属性和方法复制过来。下面看代码。对象

function Animal(){
    this.eat = function(){
        alert("我会吃");
    }
}

function Bird(){
    this.fly = function(){
        alert("我会飞");
    }
    //这里写一个继承的方法,用来复制全部父类的属性或方法
    this.extend = function(parent){
        for(var key in parent){
            this[key] = parent[key];
        }
    }
}

var pigeon = new Bird();
//执行继承的方法
pigeon.extend(new Animal());

pigeon.fly();
pigeon.eat();

这个也和上面同样同样的。

 

四、ES6标准类的继承

ES6中引入了class的概念,新的class能帮助咱们写出更好更直观的面向对象的代码。

下面这是ES6中类与类的继承,实现的效果跟上面是同样的。

class Animal {
    constructor(name){
        this.name = name;
        this.type = "动物";
    }
    
    says(say){
        console.info(this.type + "【" + this.name + "】" + "说 " + say);
    }
}

let dog = new Animal("狗狗");
dog.says("汪汪汪");


class Bird extends Animal {
    constructor(name){
        super(name);
        this.type = "小鸟";
    }
}

let pigeon = new Bird("鸽子");
pigeon.says("我是一只小鸟");

实现是很是简单直观的,并且不会再被人称为这是“模拟继承”。

 

2、各有什么缺点

一、原型链继承利弊

一、只能单继承。二、继承后会影响全部的对象。三、速度略慢。

二、原型冒充继承利弊

一、虽然能够多继承,可是没法在运行的时候动态继承,只能修改父类的构造函数。

三、复制继承(非ES6推荐)

一、无。

由于上面两个所拥有的缺点它都很好地避开了,它能够实现多继承,继承只影响当前对象,并且速度快,没必要修改父类的构造函数等等等等,因此最推荐的仍是这种继承方式。

注:jQuery的继承也是采起复制继承实现的,不过jQuery加了不少的验证判断,可是原理是同样的。

四、ES6标准类的继承

若是能使用最新的ES6的特性,这种继承是最好的,通俗易懂,是标准的面向对象的语言该有的继承方式。

可是须要注意:

子类的contructor里,“this”必须放在super()调用以后

子类的contructor里必须调用super(),或者明确地返回一个对象

不能多继承

-- Java在继承的时候会自动生成一个父类对象,可是js里并不会

相关文章
相关标签/搜索