javascript 面向对象编程之继承

构造函数、实例、原型之间的关系

每个函数都有一个prototype属性指向原型;原型内部有个constructor属性指向函数;实例有个_proto_ 指向原型,因为浏览器差异,有的浏览器不对外开放此属性。用一幅图简单描述如下(自己画的先凑活看吧^_^)

function Person(){

}
var p1 = new Person();
console.log(Person==Person.prototype.constructor);//true

这里写图片描述

原型链

基于三者的关系,可以让子类的原型指向父类的实例,那么就能实现继承。

function Person(){

}
Person.prototype.sayName=function(){
    console.log("person's sayName");
}

function Student(){

}
Student.prototype=new Person();

var s1 = new Student();
s1.sayName();

这里写图片描述
可以看到s1指向的原型就是Person实例,s1原型中含有constructor指向Person,还有_proto_指向Person prototype,在执行s1.sayName 时,首先在Student prototype寻找sayName函数,因为没有所以继续寻找上一级原型,Person prototype中有sayName,所以执行此方法。
这种方法实现的继承有个缺点就是无法往父类构造函数传参,为了解决此问题代码改为

借用构造函数

function Person(){
    this.colors=["red","blue","green"];
}

function Student(){
    Person.call(this);//调用父类构造函数
}
var t1 = new Student();
t1.colors.push("black");
console.log(t1.colors);//[ 'red', 'blue', 'green', 'black' ]

var t2 = new Student();
console.log(t2.colors);//[ 'red', 'blue', 'green' ]

这个模式的优点是可以传参,缺点就是,方法如果定义在构造函数中则犯了重复创造的毛病,所以可以将函数定义在原型上。结合原型链模式和构造函数模式,推出了组合模式。

组合模式

组合模式的思路是利用原型链来继承原型的属性和方法,利用构造函数模式继承父类的属性。

function Person(name){
    this.colors=["red","blue","green"];
    this.name=name;
}
Person.prototype.sayName=function(){
    console.log(this.name);
}
function Student(name,age){
    Person.call(this,name);//调用父类构造函数
    this.age=age;
}
Student.prototype=new Person();
Student.prototype.sayAge=function(){
    console.log(this.age);
}

var t1 = new Student("jun",30);
t1.colors.push("black");
console.log(t1.colors);//[ 'red', 'blue', 'green', 'black' ]
t1.sayName();//jun
t1.sayAge();//30

var t2 = new Student("jordan",50);
console.log(t2.colors);//[ 'red', 'blue', 'green' ]
t2.sayName();//jordan
t2.sayAge();//50

组合模式既利用了原型模式也利用了构造函数模式,是目前最常用的继承模式。

原型式继承

原型式继承就是将子类原型指向父类实例的过程封装起来了,并且不用创建子类类型就可以实现继承,简化了代码;注意原型式继承就是实现了一个浅复制,如果有引用类型要注意。

function object(o){
    function F(){

    }
    F.prototype=o;
    return new F();
}

var person={
    "name":"jordan",
    "colors":["red","blue"]
};

var o1 = object(person);
o1.name="haha";
console.log(o1.name);//haha
console.log(o1.colors);//[ 'red', 'blue' ]
console.log(o1.hasOwnProperty("name"));//true,原型上的name
o1.colors.push("black");
var o2=object(person);
console.log(o2.name);
console.log(o2.hasOwnProperty("name"));//false,实例上的name
console.log(o2.colors)//[ 'red', 'blue', 'black' ]

寄生式继承

简单来说,就是封装了继承过程的代码,并做了增强,跟原型式继承差不多。缺点就是,增强函数无法复用。

function object(o){
    function F(){

    }
    F.prototype=o;
    return new F();
}

function createAnother(original){
    var obj = object(o);
    obj.someMethod=function(){

    }
    return obj;
}

寄生组合式继承

组合式继承最大的缺点是调用了两次超类型的构造方法,第一次是在Student.prototype=new Person(); 这会在Student的原型中创建一次属性,第二次是在new Student() 这会在Student实例中又创建了一次属性。寄生组合式继承的思路是,第一次调用超类构造函数的目的是为了获取超类原型的副本,可以通过复制一份超类原型去掉这一次。

function object(o){
    function F(){

    }
    F.prototype=o;
    return new F();
}

function inheritPrototype(subType,superType){
    var obj = object(superType.prototype);
    obj.constructor=subType;
    subType.prototype=obj;
}

function Person(name){
    this.name=name;
}
Person.prototype.sayName=function(){
    console.log(this.name);
}

function Student(name,age){
    Person.call(this,name);
    this.age=age;
}
inheritPrototype(Student,Person);
var s1 = new Student("jun",30);
s1.sayName();//jun

这种模式只需要调用一次超类构造函数,是最理想的继承模式。

参考

javascript高级程序设计(第二版)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值