淺談JS中的構造函數、原型對象(prototype)、實例中的屬性/方法之間的關係

構造函數:函數中的一種,經過關鍵字new能夠建立其實例。爲了便於區分,一般首字母大寫;
原型對象:一種特殊的對象,構造函數建立時即自動生成;與構造函數造成一一對應,如同人和影子般的關係;
實例:經過構造函數實例出來的對象;函數


  在定義構造函數時,在其內部(「{「和」}」)進行定義屬性和方法。當咱們經過關鍵字new,對構造函數進行實例化的時候。實例會對構造函數的這些屬性進行拷貝出一份副本,而後將其歸屬爲當前實例。不一樣實例間的屬性和方法是徹底獨立的,以下例子:this

function Person(name,age){
    this.name = name;
    this.age = age;
    this.sayName = function(){
           alert(this.name);
    };
}

var HL = new Person("hailing",18);
var JJ = new Person("jiajia",20);

HL.sayName(); // hailing
JJ.sayName(); // jiajia

HL.name = "HAILING";

HL.sayName(); // HAILING
JJ.sayName(); // jiajia

  咱們經過建立了new對Person進行實例化兩個對象「HL」、「JJ」,當咱們在修改「HL」的名字時,「JJ」的名字不會隨之而改變。prototype

  程序執行時,會自動生成一個原型對象(prototype)與之相關聯。同時給該構造函數自動添加一個屬性:prototype,該屬性爲指針,指向原型對象。同時,也給該原型對象添加一個屬性:constructor,該屬性也爲指針,指向與其對應的構造函數。此時,原型對象中只會包含些默認的方法和屬性。指針

  實例化完成後,全部實例均會與原型對象造成多對一的隱性關聯關係。全部實例會共享原型對象的屬性和方法,固然也包括constructor。當原型對象被添加一個屬性或者方法後,均會被全部實例共享,便可以經過任意一個實例進行訪問。若是原型對象的屬性或方法與實例的屬性或方法名稱一致,則實例自身的屬性或方法優先級高於原型對象上的:code

Person.prototype.sex = "girl";
Person.prototype.saySex = function (){
   alert(this.sex);
};
alert(HL.saySex === JJ.saySex); // true
alert(HL.saySex === Person.prototype.saySex); // true

Person.prototype.stature = 165;
alert(HL.stature); // 165
alert(JJ.stature); // 165

HL.stature = 160;
alert(HL.stature); // 160
alert(JJ.stature); // 165

delete HL.stature;
Person.prototype.stature = 170;
alert(HL.stature); // 170
alert(JJ.stature); // 170

  例子中,給原型對象增長了sex屬性和saySex方法,此時經過實例對象「HL」和「JJ」訪問而且進行比較,同時也和原型對象自身的saySex進行比較,結果爲ture;然後又給原型對象增長了stature屬性,此時「HL」和「JJ」中均無此屬性,故訪問了原型對象中的stature屬性。當咱們單獨給「HL」增長了stature屬性後,「HL」不在訪問原型對象,而是訪問「HL」自身的該屬性。當咱們經過關鍵字「delete」刪除「HL」自身的屬性後,再次訪問時,又回從新訪問原型對象上的屬性。對象


總結: 構造函數中的屬性和方法僅爲聲明和定義,一旦實例化工做完成後。實例對象自身的屬性和方法與構造函數將不在存在關聯關係。原型對象與實例對象造成「備胎」關係,當經過對象訪問屬性或方法時,程序會優先搜索對象自己的屬性或方法,不存在纔會訪問原型對象的方法或者屬性。內存

  所以,當多個實例須要使用同一個屬性或方法時,咱們應該將該方法放於原型對象上,從而避免相同屬性或方法屢次獨立存在於多個對象致使內存浪費。原型

相關文章
相關標籤/搜索