Loading

js利用原型对象实现继承--Es5实现的面向对象方式

利用call和原型对象实现继承

 1 //3.利用call和原型对象实现继承
 2   //父构造函数
 3   function Father(name,age){
 4     //this指向父构造函数的对象实例
 5     this.name = name ;
 6     this.age = age;
 7     this.sing = function(){
 8         console.log('sing')
 9     }
10   }
11   //给父亲添加了money方法
12   Father.prototype.money=function(){
13     console.log('100万!')
14   }
15   //子构造函数
16   function Son(name,age,score){
17     //调用父构造函数,并修改Father的this为儿子的this,以达到调用父方法
18     Father.call(this,name,18);
19     this.score = score;
20   }
21   var wb = new Son('小王八',8,100)
22   console.log(wb);

运行结果:

 

 

 可以看到利用call可以修改父亲函数的this,使它变成子函数的this,然而继承过来的只有父亲函数里面定义的方法,父亲而外通过原型对象添加的方法,

儿子并不可以使用,与我们想的继承还是有所出入,那么这么解决呢?

直接把父亲的原型赋值给儿子好吗?

 1  //3.利用call和原型对象实现继承
 2   //父构造函数
 3   function Father(name,age){
 4     //this指向父构造函数的对象实例
 5     this.name = name ;
 6     this.age = age;
 7     this.sing = function(){
 8         console.log('sing')
 9     }
10   }
11   //给父亲添加了money方法
12   Father.prototype.money=function(){
13     console.log('100万!')
14   }
15   //子构造函数
16   function Son(name,age,score){
17     //调用父构造函数,并修改Father的this为儿子的this,以达到调用父方法
18     Father.call(this,name,18);
19     this.score = score;
20   }
21    Son.prototype =  Father.prototype ;
22   var wb = new Son('小王八',8,100)
23   var f = new Father('爸爸',50)
24   console.log(wb);
25   console.log(f)

运行截图:

 

 

 我们可以看到父亲和儿子的对象原型_proto_好像都有了money,那是不是儿子成功继承了父亲的函数了呢?

但是由于父亲有自己的函数,那么儿子也要有自己的函数,比如考试,我们给儿子添加考试函数

//3.利用call和原型对象实现继承
  //父构造函数
  function Father(name,age){
    //this指向父构造函数的对象实例
    this.name = name ;
    this.age = age;
    this.sing = function(){
        console.log('sing')
    }
  }
  //给父亲添加了money方法
  Father.prototype.money=function(){
    console.log('100万!')
  }
  //子构造函数
  function Son(name,age,score){
    //调用父构造函数,并修改Father的this为儿子的this,以达到调用父方法
    Father.call(this,name,18);
    this.score = score;
  }
   Son.prototype =  Father.prototype ;//把父亲的原型赋值给儿子
   //给儿子的原型添加自己的方法
   Son.prototype.exam = function(){
        console.log('w我考了100分!')
   }
  var wb = new Son('小王八',8,100)
  var f = new Father('爸爸',50)
  console.log(wb);
  console.log(f)

 

运行结果:

 

 

 从结果上面看,我们发现果然儿子要考试,添加成功,但是仔细一看,爸爸也要考试了!

为什么会这样呢,看下图

因为我们上面直接把父亲的原型对象给了儿子,其实相当于把地址直接赋给儿子了,那么儿子如果改了什么,父亲也会随之改动,不符合继承的性质。

正确方法:

//Son.prototype =  Father.prototype ;//把父亲的原型赋值给儿子有问题,此处为地址赋值,会引发错误
   Son.prototype = new Father();//把上面的修改成这个
 1 //3.利用call和原型对象实现继承
 2   //父构造函数
 3   function Father(name,age){
 4     //this指向父构造函数的对象实例
 5     this.name = name ;
 6     this.age = age;
 7     this.sing = function(){
 8         console.log('sing')
 9     }
10   }
11   //给父亲添加了money方法
12   Father.prototype.money=function(){
13     console.log('100万!')
14   }
15   //子构造函数
16   function Son(name,age,score){
17     //调用父构造函数,并修改Father的this为儿子的this,以达到调用父方法
18     Father.call(this,name,18);
19     this.score = score;
20   }
21    //Son.prototype =  Father.prototype ;//把父亲的原型赋值给儿子有问题,此处为地址赋值,会引发错误
22    Son.prototype = new Father();
23    //给儿子的原型添加自己的方法
24    Son.prototype.exam = function(){
25         console.log('w我考了100分!')
26    }
27   var wb = new Son('小王八',8,100)
28   var f = new Father('爸爸',50)
29   console.log(wb);
30   console.log(f)

运行结果:

 

我们看到儿子可以使用父亲的函数,也有了自己独特的函数。

上面实际修改了 Son.prototype =  Father.prototype ;

修改后变成:Son.prototype = new Father(),实际操作如下:只是拿到了Father的实例对象,然后fanther的实例对象可以拿到father原型对象的money方法,

而且儿子添加自己的方法最多修改了father的实例对象,父亲的构造函数没有影响。

 

但是上面还是有问题,因为Son.prototype = new Father(),把Father的实例对象赋值给了儿子,看似所有东西都解决了,

但是儿子里面的constructor指向父亲的构造函数了,所以还需修改儿子的constructor指向自己的构造函数。

 1 //3.利用call和原型对象实现继承
 2   //父构造函数
 3   function Father(name,age){
 4     //this指向父构造函数的对象实例
 5     this.name = name ;
 6     this.age = age;
 7     this.sing = function(){
 8         console.log('sing')
 9     }
10   }
11   //给父亲添加了money方法
12   Father.prototype.money=function(){
13     console.log('100万!')
14   }
15   //子构造函数
16   function Son(name,age,score){
17     //调用父构造函数,并修改Father的this为儿子的this,以达到调用父方法
18     Father.call(this,name,18);
19     this.score = score;
20   }
21    //Son.prototype =  Father.prototype ;//把父亲的原型赋值给儿子有问题,此处为地址赋值,会引发错误
22    Son.prototype = new Father();//把父亲实例对象赋给儿子
23    //把对象赋给儿子后,儿子的constructor也指向父亲了,需要手动指回儿子
24    //给儿子的原型添加自己的方法
25    Son.prototype.exam = function(){
26         console.log('w我考了100分!')
27    }
28   var wb = new Son('小王八',8,100)
29   var f = new Father('爸爸',50)
30   console.log(wb);
31   console.log('---------------开始测试----------------------')
32   console.log('------修改前儿子的constructor指向-------------')
33   console.log(Son.prototype.constructor)
34   Son.prototype.constructor = Son;//修改指向
35   console.log('------修改后儿子的constructor指向-------------')
36   console.log(Son.prototype.constructor)
37   console.log('---------------结束测试----------------------')
38   console.log(f)

 

 

运行结果:

 

 当然这里很麻烦,因为是Es5的时候写继承必须这样,Es6就简单了!

 

posted @ 2020-04-01 17:01  兜里还剩五块出头  阅读(276)  评论(0编辑  收藏  举报