Javascript OO 基础概念(三)–原型继承

Javascript是一门面对对象的语言,在继承特性上是基于原型链继承,通俗一点讲就是打通原型链。对于子类和超类,他们的prototype都应该形成一条链,不管直接性的还是间接性的。而这两种形式带来的效果却也有些不一样。
串联原型链:间接型

01function Person( name, age ){
02    this.name = name;
03    this.age = age;
04    this.friends = ['lsf','zxf','wzq','lk'];
05}
06Person.prototype = {
07    getName:function(){
08        returnthis.name;
09    },
10    getAge:function(){
11        returnthis.age;
12    }
13}
14functionSubPerson(){
15       this.sex ='n';
16}
17SubPerson.prototype =new Person('samir',20);
18varsubo = newSubPerson();
19alert(subo2.friends);//lsf,zxf,wzq,lk

在这个例子中,我们没有SubPerson.prototype = Person.prototype直接的串联原型链,而是让子类构造函数的prototype指向超类的一个实例,而超类的这个实例指向超类的prototype,这就一环扣一环,目的就是让子类的实例能够搜寻到超类的原型(理解这个的时候,需要明白原型查找机制)。
之所有说它是间接型的,就是因为子类的prototype指向父类的一个实例,而不是指向父类的prototype,当代码在读到子类的一个实例(subo)的一个属性friends时(subo.friends),会执行下列步骤:

* 第一步:查找实例对象是否有this.friends属性,因为我们没有在SubPerson里定义,所以会找不到,接着往下找
* 第二步:查找构造函数的原型对象是否有该属性,此时的原型对象指向Person的实例
* 第三步:构造函数的实例上确实有friends属性,好,现在查找过程结束

这就是整个继承,也就是一次逐级寻找的过程,只有把这些实例、原型都相互衔接上,才能逐级寻常。
但是它还是有缺点:超类的所有属性和方法都被连接到子类的prototype上,这就引发了上一篇中的问题,引用类型可被修改。

01function Person( name, age ){
02        this.name = name;
03        this.age = age;
04        this.friends = ['lsf','zxf','wzq','lk'];
05    }
06    Person.prototype = {
07        getName:function(){
08            returnthis.name;
09        },
10        getAge:function(){
11            returnthis.age;
12        }
13    }
14
15    functionSubPerson(){}
16    SubPerson.prototype =new Person('samir',20);
17
18    varf1 = new SubPerson();
19        //修改子类实例对象f1.friends属性
20    f1.friends.push('laozi');
21
22    varf2 = new SubPerson();
23         //结果却在f2上反映出来了,这下子问题就玩大了,他们的设计原则应该是具有相互独立的属性,这不符合这个原则
24    alert(f2.friends);

第一种的缺点带来了第二种的思考,1、我们可以把实例对象的特权属性或方法被子类借用,2、子类的prototype指向父类prototype
串联原型链:直接型

要实现实例对象的特权属性或方法为子类借用,这到底是个什么样的概念,到底什么是借用?
看看这个例子:

01function Person( ){
02    this.name ='samir';
03    this.age = 24;
04    this.friends = ['lsf','zxf','wzq','lk'];
05}
06function Son(){
07        //核心代码就是这一行,
08        //调用父类的构造函数,内部的this指向Son内的this
09        //原理:函数的调用概念很重要,等于就是在特定的地方执行一段代码和创建作用域
10        //这里就是在Son内执行了this.name = 'samir',this.age = 24,this.friends = [...]
11    Person.call(this);
12    this.name ='zsen';
13}
14    varf1 = new Son();
15    alert(f1.name);
16    alert(f1.age);

从这个例子中,我们就实现了子类与父类构造函数的继承。接下来要做的就是原型与原型的继承。这段代码在里有:

01   functionobject( o ){
02    functionF(){}
03    F.prototype = o;
04    returnnew F();
05}
06function inherit(subF,superF){
07    varprototype = object( superF.prototype);
08        prototype.constructor = subF;
09        subF.prototype = prototype;
10}
11function Person(){
12    this.name ='samir';
13    this.age = 24;
14    this.friends = ['lsf','zxf','wzq','lk'];
15}
16Person.prototype = {
17    getName:function(){
18        returnthis.name;
19    },
20    getAge:function(){
21        returnthis.age;
22    }
23}
24function Son(){
25    Person.call(this);
26    this.name ='zsen';
27}
28inherit(Son,Person);

我们可以测试下

1    varf = new Son();
2f.friends.push('samir');
3alert(f.friends);
4var f2 = new Son();
5alert(f2.friends);

从测试中可以看出,prototype上方法的共享,引用类型可以定义成构造函数的属性或对象了,实例对象都可以有自己的属性了,这些都是这种方式的优点,解决了一切的问题,而且父类构造函数的只调用了一次,哎,兴奋的我难以再写下去了,只能默默的享受着那份久违的幸福。只想说,我们真的很庆幸,有这些大牛的研究与分享,谨代表中国人民感谢你们。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值