上一節說到,咱們使用原型+構造函數混合的方式建立了一個對象,這個對象很好的區分了實例對象的私有屬性和它們的共享屬性,代碼是這樣的前端
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.必定不能在重寫原型以前實例化對象,這樣會切斷實例化對象與新原型的連接,致使沒法調用新原型中的方法
待續
...