閱讀453 返回首頁    go 阿裏雲 go 技術社區[雲棲]


再談JavaScript中對象的prototype鏈

ECMAScirpt可以識別兩種類型的對象:

    1.Navtive Object 指語言級別的對象

    2.Host Object 有運行環境提供如:document

 

Native objects是一種鬆散的結構並且可以動態的增加屬性(property),所有的屬性都有一個名字和一個值,這個值可以是另一個對象的引用,或者內建的數據類型(String ,Number,Boolean,Null,Undefined).

 

下麵我們通過一個簡單的例子,來看看一個JavaScript是如何設置一個屬性的值和讀取一個屬性的值。

var objectRef = new Object();//create a generic javascript object

下麵來為該對象添加屬性:

objectRef.testNumber = 5; /* - or:- */ objectRef["testNumber"] = 5; 

一個名為testNumber的屬性就這樣被創建。

如果賦值的屬性的名稱已經存在,那麼就不會再次創建這個屬性,賦值操作僅僅是重新設置屬性的值objectRef.testNumber = 8; /* - or:- */ objectRef["testNumber"] = 8; 

 

JavaScript對象的原型(prototype)本身也是對象,也可以有屬性(property),對於JavaScript對象的prototype的賦值操作更普通的對象沒有什麼不同,那麼對於取值操作來說就不同了,下麵我們具體來看取值操作:

 

取值操作

在取值操作中prototype和property就不一樣了,首先來看最簡單的取值操作.

/*為一個對象的屬性賦值,如果這個對象沒有這個屬性,那麼在賦值操作後,這個對象就有這個屬性了 */ objectRef.testNumber = 8; /* 讀出這個屬性的值 */ var val = objectRef.testNumber; /* 現在val 就得到了剛才賦予objectRef的值8了*/

prototype揭密

 

 

我們首先整明白這幾句話

  1. 所有的對象都可以有prototypes。
  2. prototypes自己也是對象,那麼他也可以有prototypes,這樣循環下去就形成了一個prototype鏈。
  3. 這個鏈當他遇到鏈中隊形的prototype是null時中止。(Object的默認的prototype是null)

下麵具體來看代碼:

var objectRef = new Object(); //create a generic javascript object.

 

創建一個新的JavaScript對象,這時這個對象的prototype是Null,所以objectRef的prototype鏈隻包含一個對象Object.prototype。

 

繼續看代碼:

 

/* 構建MyObject1這個類型的構造函數 MyObject1 - type. */ function MyObject1(formalParameter){ /* 為者對象創建一個屬性名字叫testNumber */ this.testNumber = formalParameter; } /* 構建MyObject2這個類型的構造函數 MyObject2 - type:- */ function MyObject2(formalParameter){ /* 為者對象創建一個屬性名字叫testString*/ this.testString = formalParameter; } /* 下一步的操作會用MyObject1對象替換掉MyObject2默認的prototype屬性*/ MyObject2.prototype = new MyObject1( 8 ); /* 最後我們創建MyObject2類型的一個對象*/ var objectRef = new MyObject2( "String_Value" );

下麵來解釋這段代碼:

  1. objectRef這個MyObject2類型的對象有一個prototype的鏈,鏈中的第一個對象是MyObject1對象。
  2. MyObject1對象也有prototype,這個prototype是Object默認的prototype
  3. Object.prototypeprototype是null,至此這條prototype鏈結束。

因此當一個取值操作發生時,objectRef 的整個prototype鏈就開始工作

var val = objectRef.testString;

objectRef這個對象的有一個屬性叫做testString,那麼上麵這句代碼會把testString的值賦給val

 

var val = objectRef.testNumber;

在objectRef這個對象裏並沒有testNumber這個屬性,但是val卻的到了值8,而不是undefine,這是因為解釋器在沒有在當前對象找到要找
的屬性後,就會去檢查這個對象的prototype,objectRef的prototype是MyObject1對象,這個對象有testNumber這個屬性,所以val得到8這個值。

 

var val = objectRef.toString;

現在val是個function的引用,這個function是Object.prototype的property,由於MyObject1和MyObject2都沒有定義toString這個property
所以Object.prototype返回

 

var val = objectRef.madeUpProperty;

最後val是undefined,因為MyObject1和MyObject2,還有Object都沒有定義madeUpProperty這個property,所以得到的是undefine.

 

讀操作會讀取在obj自己和prototype 鏈上發現的第一個同名屬性值。

寫操作會為obj對象本身創建一個同名屬性(如果這個屬性名不存在
這就意味著objectRef.testNumber = 3會在objectRef對象上創建一個property,名字是testNumber,當下一次在要讀取testNumber時
propertype鏈就不會工作,僅僅會得到objectRef的property 3,而MyObject1的testNumber屬性並不會被修改).

由下麵的代碼為證:

 

/* 構建MyObject1這個類型的構造函數 MyObject1 - type. */ function MyObject1(formalParameter){ /* 為者對象創建一個屬性名字叫testNumber */ this.testNumber = formalParameter; } /* 構建MyObject2這個類型的構造函數 MyObject2 - type:- */ function MyObject2(formalParameter){ /* 為者對象創建一個屬性名字叫testString*/ this.testString = formalParameter; } /* 下一步的操作會用MyObject1對象替換掉MyObject2默認的prototype屬性*/ var obj1 = new MyObject1( 8 ); MyObject2.prototype = obj1; /* 最後我們創建MyObject2類型的一個對象*/ var objectRef = new MyObject2( "String_Value" ); alert(objectRef.testNumber); objectRef.testNumber = 5; alert(objectRef.testNumber); alert(obj1.testNumber);

 

 



最後更新:2017-04-02 00:06:41

  上一篇:go php實現驗證碼的識別(中級篇)
  下一篇:go DB2 setting in linux