zoukankan      html  css  js  c++  java
  • 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就简单了!

    穷则独善其身,达则兼济天下……
  • 相关阅读:
    模版
    列表项模版
    vue eventBus 跳坑的办法
    vue适配移动端px自动转化为rem
    pc端,移动端css重置样式
    vue全局引入scss文件(推荐)
    vue安装scss,并且全局引入
    mapState
    通俗易懂的vuex-demo
    ve2.0 v-for循环报错的解决方案
  • 原文地址:https://www.cnblogs.com/hmy-666/p/12613802.html
Copyright © 2011-2022 走看看