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


 

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

本帖只講Object.create()。因為我也才做一年前端,理解不對的,希望大牛們幫忙指正。

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

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

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

  3、通過new 創建的對象是沒有 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.prototype

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 

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

  

  有理解不對的,希望大牛指正,不勝感激。

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM