javascript Object.create()究竟發生了什麼

 

  這是我在博客園的第一篇博客,早上看了一個大牛的博客,關於javascript繼承的,對於大牛使用Object.create()實現繼承的方式以爲點問題,就本身研究了一下,因此就有了這篇帖子。javascript

本帖只講Object.create()。由於我也才作一年前端,理解不對的,但願大牛們幫忙指正。前端

  在博客開始前先談下我多 prototype和__proto__的粗淺的認識。java

  一、prototype 只有類纔有這個屬性,通常經過函數聲明 function xx(){} 和函數表達式 var xx=function(){} 定義的對象都有這個屬性,而經過new生成的函數對象則沒有這個屬性。類的prototype屬性指向類的原型對象函數

  二、__proto__  這個指向父類的prototype屬性所指向的對象,即父類的原型對象; 函數聲明和函數表達式定義的類的__proto__指向Object的原型對象function Empet(){}.好比 function A(){} ;  var a= new A(); a.__proto__和A.prototype指向的是同一個對象。this

  三、經過new 建立的對象是沒有 prototype屬性的spa

  先上一張圖片,這樣你們瞭解的比較清楚。圖應該你們都看得懂,這裏就不解釋了。prototype

  基於以上粗淺的認識開始下面的探討。翻譯

  先建立類A調試

function A(){
    this.x="i am x"
}
var a =new A(); console.log("A.prototype : "+A.prototype+" ,A.__proto__ : "+A.__proto__);//A.prototype : [object Object] ,A.__proto__ : function Empet(){}驗證第一點 console.log("a : "+a.prototype+" ,a.__proto__ : "+a.__proto__); //a : undefined ,a.__proto__ : [object Object] 驗證第3點

  驗證驗證 第二點a.__Proto__ 就是 A.prototypecode

a.__proto__.getName=function(){
	console.log("create by a.__proto__");
}
var a2 =new A();
a2.getName();  //create by a.__proto__

  驗證成功,經過new建立的對象的__proto__跟類的prototype指向同一個對象,即類的原型對象

 

  如今開始正題——Object.create 發生了什麼

var obj =Object.create(A);

  《javascript權威指南》6.1節中說 Object.create()建立一個新對象,其中第一個參數是對象的原型。

  若是按照這種說法 obj.prototype 應該指向A;因此obj.prototype跟A擁有相同的方法和屬性,如今爲A定義一個show方法 看obj.prototype是否能調用這個show()方法

A.show=function(){
    return "i am A"
}
console.log("A.show(): "+A.show());  //A.show(): i am A

  A能調用show方法,驗證obj.prototype 是否能調用show()方法

console.log("obj.prototype: "+obj.prototype.show());//報錯 undefined is not a function

  oh,mygod,難道我心中的聖經《javascript權威指南》上寫的是錯的嗎?我寧肯相信是我理解錯了,或是翻譯錯了。

  通過斷點調試發現,obj擁有__proto__屬性而沒有prototype屬性。我前面也說過,在我粗淺的認識中, 只有經過new建立的對象纔有這樣的性質——有__proto__屬性而沒有prototype屬性。因此我判定obj是經過new建立的對象。斷點調試發現 obj的_proto__是指向A的。

  查閱了一下資料 微軟的官方文檔上是這樣寫的

  "Object.create()返回值爲一個具備指定的內部原型且包含指定的屬性(若是有)的新對象" 注意這裏 "指定的內部原型" 指定的內部原型是__proto__ 而不是prototype。咦,難道真的是這樣嗎?

  若是是這樣的話就是說  obj是new出來的對象, 在Object.create() 過程當中 產生了一個類 這個類是obj的父類。父類new出了obj這個實例對象。 父類的prototype是指向A的, 因此obj的__proto__就指向了A。

  爲了驗證這個想法,程序走起。

console.log("obj.__proto__.show(): "+obj.__proto__.show()); //obj.__proto__.show(): i am A
console.log("obj.x : "+obj.x);  //undefined   oh soga。這個是正常的,由於A中定義x是this.x="i am x"  x是A實例的屬性,obj報undefined是正常的

  obj的__proto__可以調用show()方法,說明obj的__proto__確實指向A  

  關於第二個驗證obj.x是多餘的。obj 自己沒有x屬性,沿着原型鏈 obj的prototype Object.create()建立的父類也沒有定義x。obj的prototype的prototype也就是A,A函數裏面有x,可是A自己沒有定義x因此報undefined是正常的。果真基礎不夠紮實,才寫了這多餘的驗證。

  再隨便看下原型鏈繼承。

A.x="gg";
console.log("obj.x A have defined x : "+obj.x); //obj.x A have defined x : gg

  果真跟想的同樣,obj沒有x,它就需找它的父類(obj_father),父類沒有定義this.x,注意這裏是this.x 而不是父類.x(obj_father.x)。在父類中只有this.x才能被子類調用。父類.x是父類本身的私有屬性。父類沒有x因此找到父類的prototype即A。A有.x 因此就輸入A的x。沒有A沒有就報undefined;

  就剛剛突發奇想 想看一下new一個實例對象會產生什麼後果。

var b= new obj();//object is not a function 

  看到這個,我不得不嘲笑本身,原本就該這樣,都不願思考,還要寫個程序驗證!!!基礎啊基礎

  

  有理解不對的,但願大牛指正,不勝感激。

相關文章
相關標籤/搜索