• JavaScript学习总结--创建对象(4_原型扩展)


    上一节说到,我们使用原型+构造函数混合的方式创建了一个对象,这个对象很好的区分了实例对象的私有属性和它们的共享属性,代码是这样的

    function Person(name,age,job){
      this.name=name;
      this.age=age;
      this.job=job;
    }
    Person.prototype.sayName=function(){
      console.log(this.name);
    }
    var person_01=new Person("Sakura",22,"前端开发");
    var person_02=new Person("Misaka",20,"网页设计");

    那么问题又来了,当我们需要在Person类的原型上添加更多的属性和方法时,就不可避免的要一遍又一遍的重写Person.prototype.XXX=XXX

    很显然我们是不愿意这样写的

    我们知道原型实际上也是一个对象,是对象那它就可以用字面量的方式重写

    理所当然的我们可以这样写

    //省略之前代码
    Person.prototype={
      sayName:function(){
        console.log(this).name;
      },
      sex:"man",
      country:"China"
    }

    但是这里有一个问题需要注意,我们知道原本Person的原型对象有一个constructor属性,指向Persou构造函数本身

    而当我们用字面量的方式重写了原型对象以后,就相当于抹去了它原本的所有属性,直接将一个新对象赋值给了prototype对象,那么这时原本它隐含的constructor就被改写了,重写后的原型对象constructor属性指向就变成了Object,而非原本的Person,所以这里们需要人为的改写原型对象的constructor属性

    Person.prototype={
      constructor:Person,
      //...  
    }

    保证通过字面量重写后的原型对象和构造函数保持连接的关系

    重写原型时有一点非常重要

    我们先来看一个例子

    function Person(name,age){
      this.name=name;
      this.age=age;
    }
    var person_01=new Person("Sakura",22,"前端开发");
    //注意这里先实例化了对象person_01,然后才在原型上添加了sayName方法
    Person.prototype.sayName=function(){
      console.log(this.name);
    }
    
    person_01.sayName();        //Sakura

    这里我们先实例化了对象,然后才添加了sayName方法,而调用后是没有问题的,因为当我们调用sayName方法时,它会先从构造函数内部寻找,没有找到则继续往上在袁兴中查找,实例与原型的链接是一个指针,一个引用,这也说明我们随时可以用这种方式给原型添加新的属性和方法

    但是,当我们实例化person_01对象后再用字面量的方式重写原型对象,就有问题了

    function Person(name,age){
      this.name=name;
      this.age=age;
    }
    var person_01=new Person("Sakura",22,"前端开发");
    
    Person.prototype={
      sayName:function(){
        console.log(this.name);
      }
    }
    
    person_01.sayName();        //error

    原本在原型上添加方法和属性时,实例对象person_01始终与原型保持连接关系(通过__proto__),所以无论何时给Person原型添加属性方法都能被实例对象寻找到

    但是上面说到,当我们用字面量重写原型对象后,实际上是为原型赋值了一个新对象,而这个新的原型还没有和实例对象person_01建立连接,也就是说此时person_01的__proto__属性指向的是重写前的原型对象,而非重写后的新原型对象,调用时,从重写前的原型对象里并不能找到sayName方法,所以发生了错误

    所以通过字面量重写原型有两个非常重要的问题需要注意

    1.重写后的原型constructor指向Object,需要人为的修改constructor属性指向原本的构造函数

    2.一定不能在重写原型之前实例化对象,这样会切断实例化对象与新原型的链接,导致无法调用新原型中的方法

    待续

    ...

  • 相关阅读:
    Android的startActivityForResult()与onActivityResult()与setResult()参数分析,activity带参数的返回
    git stash 保存当前工作状态
    vim diff 的使用
    git pull 命令
    java 开发环境安装
    vim 处理换行符
    git 操作分支
    git 操作远程仓库地址
    vim 宏的使用
    Chrome 调试技巧
  • 原文地址:https://www.cnblogs.com/sakura-log/p/5552811.html
Copyright © 2020-2023  润新知