PHP8.1.21版本已发布
vue8.1.21版本已发布
jquery8.1.21版本已发布

javascript继承方式详解

高洛峰
高洛峰 原创
2016-11-16 11:30:01 993浏览

继承方式主要有六种:

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();
声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。