js的继承:原型链继承,借用构造函数继承,组合继承,原型式继承,寄生式继承,寄生组合式继承

1,300 阅读3分钟
想要继承都必须要有一个父类,不然你继承谁的遗产去。

一.原型链继承

//父类
function father(name){
this.name = name;
this.fatherName = function(){
    alter(this.name)
}
}
//给构造函数添加原型属性
father.prototype.age = 10;
//子类
function sun(){
    this.name = "sun"
}
sun.prototype = new father()//sun的原型等于父类的实例
var sun1 = new sun();
console.log(sun1.age);//输出结果为 10

console.log(sun1 instanceof father)//输出结果为true
//instanceof运算符用来判断一个构造函数的prototype属性所指向的对象是否存在另外一个要检测对象的原型链上
//因为sun1继承了father,所以返回true

特点:1、实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型的属                    性。(新实例不会继承父类实例的属性!)

缺点:1、新实例无法向父类构造函数传参。
   2、继承单一。
     3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修改了                   原型属性,另一个实例的原型属性也会被修改!)

二、借用构造函数继承

//父类
function father(name){
this.name = name;
this.fatherName = function(){
    alter(this.name)
}
}
//给构造函数添加原型属性
father.prototype.age = 10;
//子类
function sun(){
    father.call(this,'father');//sun指向father
    this.age = 12;
}
var sun1=new sun();
console.log(sun1.age)//12
console.log(sun1.name)//'father'
console.log(sun1 instanceof father)// false

特点:1、只继承了父类构造函数的属性,没有继承父类原型的属性。
   2、解决了原型链继承缺点
   3、可以继承多个构造函数属性(call多个)。
   4、在子实例中可向父实例传参。

缺点:1、只能继承父类构造函数的属性。
   2、无法实现构造函数的复用。(每次用每次都要重新调用)
   3、每个新实例都有父类构造函数的副本,臃肿。

三、组合继承(组合原型链继承和借用构造函数继承)(常用)

//父类
function father(name){
this.name = name;
this.fatherName = function(){
    alter(this.name)
}
}
//给构造函数添加原型属性
father.prototype.age = 10;
//子类
function sun(name){
    father.call(this,name);
}
sun.prototype = new father();
var sun1 = new sun('张三')
console.log(sun1.name)//张三
console.log(sun1.age)//10

特点:1、可以继承父类原型上的属性,可以传参,可复用。
   2、每个新实例引入的构造函数属性是私有的。
缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。

四、原型式继承

//父类
function father(name){
this.name = name;
this.fatherName = function(){
    alter(this.name)
}
}
//给构造函数添加原型属性
father.prototype.age = 10;
//子类
 function sun(obj){
    function fn(){}
    fn.prototype = boj;
    return new fn();
}
var father1 = new father();
var sun1 = new sun(father1);
console.log(sun1.age)// 10

用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象。object.create()就是这个原理。

使用场合:没必要构建构造函数,仅仅是想模拟一个对象的时候

 特点:类似于复制一个对象,用函数来包装。
 缺点:1、所有实例都会继承原型上的属性。
    2、无法实现复用。(新实例属性都是后面添加的)

五、寄生式继承

//父类
function father(name){
this.name = name;
this.fatherName = function(){
    alter(this.name)
}
}

//子类
 function sun(obj){
    function fn(){}
    fn.prototype = boj;
    return new fn();
}

function others(obj){
    var sun1 = sun(obj);
    sun1.name = '张三';
    return sun1;
}
var father1 = new father();
var sun2 = others(father1);
console.log(typeof others)//function
console.log(typeof sun2) //object
console.log(sun2.name)//张三

优点:没有创建自定义类型,因为只是套了个壳子返回对象(这个),这个函数顺理成章就成            了创建的新对象。

缺点:没用到原型,无法复用。

 六、寄生组合式继承(常用)

//父类
function father(name){
this.name = name;
this.fatherName = function(){
    alter(this.name)
}
}
//给构造函数添加原型属性
father.prototype.age = 10;
function sun(obj){
    function fn(){};
    fn.prototype = obj;
    return new fn();
}
function sub(){
    father.call(this)
}
var con = sun(father.prototype);
sub.prototype = con;
con.constructor = sub; //修复实例
var sub1 = new sub();
console.log(sub1.age);//10