javascript 继承解读

回顾:构造函数,原型,实例三者的关系

每一个构造函数都有一个原型对象(Person.prototype);原型对象都包含指向构造函数的指针(constructor);每个实例都包含指向原型对象的指针(看不见的_proto_指针)

继承:子对象继承了父对象。

特点:继承后的子对象会拥有父对象的属性和方法。(假如你爸爸的100亿、豪车、豪宅、公司、人脉等等都给你了,你说是开心呢?还是开心呢?.....哈哈哈哈,这是个比喻......老铁醒醒了,我们继续知识点解读)

继承有很多方法,下面会说几个类型,也会给出案例,案例参考了  https://blog.csdn.net/js_admin/article/details/71012367 的案例 ,个人感觉写的还是比较还理解的。

1、原型链继承

        //  父类 
        function father (name,age){ 
        	this.name = name; 
        	this.age = age; 
        }
        // 父类的原型对象属性 
        father.prototype.id = 10;

        // 子类 
        function son (sex){ 
        	this.sex = sex;
        }

        // 继承实现方法
        son.prototype = new father('c5',27);
         var jicheng = new son('girl'); 
         alert(jicheng .name)// c5 
         alert(jicheng .id)//10
         alert(jicheng .sex)//girl

         优点:
            非常纯粹的继承关系,实例是子类的实例,也是父类的实例
            父类新增原型方法/原型属性,子类都能访问到
            简单,易于实现
         缺点 :
            
            可以在子构造函数中,为子实例增加实例属性。
            如果要新增原型属性和方法,则必须放在new father()这样的语句之后执行。
            
            来自原型对象的所有属性被所有实例共享。

            创建子类实例时,无法向父类构造函数传参

2、类继承(构造函数方式)

       
       function father(name,age){ 
		        	this.name = name; 
		        	this.age = age; 
		}
        father.prototype.id = 10;
        function son(name,age,sex){ 
        	father.call(this,name,age); 
               //使用了call 方法来继承,也可以apply(参数一,数组)但是call和apply会立执行
               //注意如果call和apply的第一个参数写的是null,那么this指向的是window对象
        	this.sex = sex;
        }
         var jicheng = new son('c',27,'男'); 
         console.log(jicheng.name) // c
         console.log(jicheng.sex)  // 男
         console.log(jicheng.id)   //undinfind 父类的原型对象并没有继承,也无法继承

         特点: 继承了父类的模板,不继承了父类的原型对象。
         优点:  解决了1中,子类实例共享父类引用属性的问题
                创建子类实例时,可以向父类传递参数
                可以实现多继承(call多个父类对象)
         缺点:  不继承了父类的原型对象 
                不能继承原型属性/方法 (原型中定义的方法和属性对于子类是不可见的)
                实例并不是父类的实例,只是子类的实例
                只能继承父类的实例属性和方法,不能继承原型属性/方法
                无法实现函数复用,每个子类都有父类实例函数的副本,影响性能
         补充:因为方法和属性只能写在构造函数中,因此不能实现函数复用 只能继承父类的实例属性和方法,
         

3、合并继承(原型继承和类继承共同作用)

       function father(name,age){ 
        	this.name = name; 
        	this.age = age; 
       }
        father.prototype.id = 10;
        function son(name,age,sex){ 
        	father.call(this,name,age);
        	this.sex = sex;
        }
	     son.prototype = new father();
         var jicheng= new son('xiansan',27,'男'); 
         alert(jicheng.name)// xiansan
         alert(jicheng.id)//10

        这种原型继承的特点:既继承了父类的模板,又继承了父类的原型对象。
        优点方便了子类实例传参
        缺点就是son.pertotype = new Persion()  函数又实例一次,
        函数内部变量又重复实例一次,大程序时候会很好性能。

4、【原型式继承】借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型。从本质上讲,object()对传入其中的对象执行了一次浅复制。
  [注意]原型式继承要求必须有一个对象可以作为另一个对象的基础,如果有这么一个对象的话,可以把它传递给object()函数,然后再根据具体需求对得到的对象加以修改即可

function object(o){
  function F(){};
  F.prototype = o;
  return new F();
}
var person = {
  name: "Nicholas",
  friends: ["Shelby","Court","Van"]
};
var anotherPerson = object(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");

var yetAnotherPerson = object(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");

alert(person.friends);//"Shelby,Court,Van,Rob,Barbie"

5、【寄生式继承】创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真的是它做了所有工作一样返回对象
[缺点]无法实现函数复用

function object(o){
 function F(){};
 F.prototype = o;
 return new F();
}
function createAnother(original){
 var clone = object(original);//通过调用函数创建一个新对象
 clone.sayHi = function(){ //以某种方式来增强这个对象
  alert("hi");
 };
 return clone;//返回这个对象
}
var person = {
 name: "Nicholas",
 friends: ["Shelby","Court","Van"]
};
var anotherPerson = createAnother(person);
anotherPerson.sayHi();//"hi"

6、【寄生组合式继承】通过借用构造函数来继承属性,通过原型链的混成形式来继承方法。其背后的基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,所需的无非就是超类型原型的一个副本而已。本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。寄生组合式继承是引用类型最理想的继承范式。

//这个例子中的高效率体现在它只调用了一次Super构造函数,并且因此避免了在SubType.prototype上面创建不必要的、多余的属性。与此同时,原型链还能保持不变。
function object(o){
 function F(){};
 F.prototype = o;
 return new F();
}
function inheritPrototype(subType,superType){
 var prototype = object(superType.prototype);//创建对象
 prototype.constructor = subType;//增强对象
 subType.prototype = prototype;//指定对象
}
function SuperType(name){
 this.name = name;
 this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function(){
 alert(this.name);
};
function SubType(name,age){
 SuperType.call(this,name);
 this.age = age;
}
inheritPrototype(SubType,SuperType);
SubType.prototype.sayAge = function(){
 alert(this.age);
}

 

 

 

 

 

 

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值