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函数

很显然咱们是不肯意这样写的this

咱们知道原型实际上也是一个对象,是对象那它就能够用字面量的方式重写spa

理所固然的咱们能够这样写prototype

//省略以前代码
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,
  //...  
}

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

重写原型时有一点很是重要对象

咱们先来看一个例子blog

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.必定不能在重写原型以前实例化对象,这样会切断实例化对象与新原型的连接,致使没法调用新原型中的方法

 

待续

...

相关文章
相关标签/搜索