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.必定不能在重寫原型以前實例化對象,這樣會切斷實例化對象與新原型的連接,致使沒法調用新原型中的方法

 

待續

...

相關文章
相關標籤/搜索