上一节说到,咱们使用原型+构造函数混合的方式建立了一个对象,这个对象很好的区分了实例对象的私有属性和它们的共享属性,代码是这样的前端
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.必定不能在重写原型以前实例化对象,这样会切断实例化对象与新原型的连接,致使没法调用新原型中的方法
待续
...