继承方式主要有六种:

1、原型链继承  存在对象共享的问题

2、构造函数继承  借助call apply方法实现  :函数复用性问题 每次实例化,都重新执行了一次父类,父类中的方法重复定义  

3、组合模式(原型链+构造函数)构造函数继承属性,原型链继承方法  :解决了对象共享,但是属性继承出现两次

4、原型方式 使用一个空间空函数

5、寄生方式  在原型方式上增加额外了方法

6、寄生组合方式(解决了属性继承出现2次的问题)

 

 

1、原型链方式

子类在继承父类时,是将子类的prototype指向父类的一个实例对象。 在子类实例化时,所有子类的实例都会共享父类的那个实例上(假设叫p)的属性和方法,如果p上有引用型的属性,则子类的实例可以修改该引用型的属性,导致其他实例上的该属性也被修改。

//原型链方式
function A(){
    this.name = 'lc';
    this.stus = ['a','b','c'];
}
A.prototype.introduce = function (){
    alert(this.name);
}

function B(){}
B.prototype = new A();

var s1 = new B();
var s2 = new B();
console.log(s1.stus);  //['a','b','c']  
s1.stus.push('d');     //改变s1上的属性,会影响s2上的该属性
console.log(s2.stus);  // ['a','b','c','d']

如果改成下面的,则不会影响。

//原型链方式
function A(){
    this.name = 'lc';
    this.stus = ['a','b','c'];
}
A.prototype.introduce = function (){
    alert(this.name);
}

function B(){}
B.prototype = new A();

var s1 = new B();
var s2 = new B();

s1.stus = ['d'];   //在s1上增加了属性,  就近原则,不在查找原型链上的同名属性
console.log(s1.stus);  //['d']
console.log(s2.stus);  // ['a','b','c']

 

2、构造函数方式继承

  共用构造函数,方法都是在内部定义,复函复用性问题无从谈起。

//构造函数方式继承
function A(name){
    this.name = name;
    this.type = 'parent';
    this.introduce = function (){ alert(this.name);}
}
A.prototype.sayhi = function (){
    alert(this.type);
}
function B(name,age){
    A.call(this,name);  //使用call方法 实现继承 但是父类中的方法重复定义 无复用性
    this.age = age;
    this.introduce = function (){ alert(this.name+this.age);}
}

var b = new B('lc',25);
b.introduce(); //lc25
b.sayhi();  //parent

3、混合方式 (原型方式+构造函数方式) 

使用构造函数继承属性,原型链继承方法

但是有一点不好的地方:  使用原型链继承时,实际上属性也继承了,重复了。 

function A(name){
    this.name = name;
    this.type = 'parent';
}
A.prototype.sayhi = function (){
    alert(this.type);
}
function B(name,age){
    A.call(this,name);
    this.age = age;
    this.introduce = function (){ alert(this.name+this.age);}
}
B.prototype = new A();

4、原型式继承

使用了一个中间空函数,实现继承后,返回一个对象。

function extend(parent){
    function F(){}
    F.prototype = parent;
    return new F();
}

 5、寄生式继承  在原型式的基础上,再为对象添加属性 方法

function extend(parent){
    function F(){}
    F.prototype = parent;
    return new F();
}

function createObj(p){  
    var clone = extend(p);
    clone.name = 'hello';    
    clone.say = function (){}
    return clone;
}

 

6、寄生组合式继承

在继承方法的时候,不再实例化父类型的构造函数,而是使用inheritPrototype方法. 使用一个中间空函数,让这个空函数去继承父类原型,然后实例化这个空函数(继承了父类prototype中的所有方法)。将子类的原型指向这个实例化的空对象即可。

避免了实例化父类的构造函数。

/* 寄生组合式继承 */
function inheritPrototype(subType, superType) {
  // var obj= extend(superType.prototype);
  function F(){}
  F.prototype = superType.prototype;
  var obj= new F();

  //obj.constructor = subType;
  subType.prototype = obj;    //不可将subType的prototype直接指向superType,否则的话,对子类prototype的修改会反应到父类上,  引用型变量
subType.prototype.constructor = subType;
}

 

 

 

 

 

 

 

 

对象冒充: 使用构造函数的方式声明类,将一个类的方法指向另一个构造函数(因为构造函数本身就是一个方法函数),实现继承

function A(){
    this.name = {name1:'hello'};
    this.say = function (){ console.log(this.name);}
}
function B(){
    this.method = A;
    this.method();
    delete this.method;
}
 var bObj = new B();

 

分类:

技术点:

相关文章: