2011-08-03 79 views
6

我剛剛收到了Javascript:Douglas Crockford的Good Part,我在理解他的一個關於原型的例子時遇到了一些困難。本書中的代碼如下:關於javascript練習的混淆

if (typeof Object.create !== "function") { 
    Object.create = function(o) { 
     var F = function() {} 
     F.prototype = o; 
     return new F; 
    }; 
} 

我假設這段代碼是用來定位函數的原型。但爲什麼要使用這種複雜的方法?爲什麼不使用variable。原型? Crockford是Javascript領域的頂尖專家,所以我相信使用這個模型有一個很好的理由。任何人都能幫助我更好地理解它嗎?任何幫助,將不勝感激。

回答

5

在ECMAScript中如圖3所示,操作者new是設置對象的[[Prototype]]內部屬性,在這種情況下,克羅克福德只是使用臨時構造函數F用於該目的的唯一標準方式。

該方法的o參數,設置爲臨時構造的prototype屬性,並通過調用new F();它建立從F.prototype繼承一個新的空對象(見this question爲更多細節如何new作品)。

例如:

var a = { a: 1 }; 
var b = Object.create(a); // b inherits from a 
b.a; // 1 

在上面的例子中,我們可以說,b的內部[[Prototype]]屬性指向a

Object.getPrototypeOf(b) === a; // true 

換句話說,從ab繼承。

用上面的例子,我們可以使用一個空的構造,如:

function F(){} 
F.prototype = a; 

var b = new F(); // b again inherits from a (F.prototype) 

還記得的功能prototype性質大於[[Prototype]]屬性,所有對象都具有不同的功能prototype屬性在用新操作符調用它們時使用,以構建從該屬性繼承的新對象。

另外,請注意,現在,ECMAScript 5標準正在實施中,並且此墊片不符合規範100%,實際上,標準Object.create方法that cannot be emulated on ES3有一些功能。

參見:

+0

@ CMS - 但在這種情況下,Object.create被設置爲空函數。所以這裏沒有遺產......對吧?另外,由於Object.create是Object構造函數的一個方法,因此將它設置爲一個空函數會是null。 – dopatraman

+0

@codeninja,我不明白你爲什麼說'Object.create' *設置爲*空*功能,可能是由於最後一行('return new F;')???最後一行只是返回一個調用'F'構造函數的新對象(一個繼承自'F.prototype'的對象),它可能看起來並不熟悉,因爲最後缺少括號,但在使用'new ('new F();'相當於'new F;')... – CMS

+0

@ CMS - 代碼讀取'Object.create = var F',將'='設置爲'function(){ }'。這是否意味着它在某種意義上被設置爲空函數? – dopatraman

0

此創建方法將實例化一個給定傳遞對象作爲原型的新對象。

+0

@ Nathan_Romano - 爲什麼不只是使用'new'對象? – dopatraman

3
var bar = Object.create(foo) 

var bar = new Object() 

第一bar具有foo作爲其原型;第二個以Object爲原型。

+0

Typo:「第二個'Object'作爲其原型'應該是'第二個'Object.prototype'作爲其原型...'('Object'只是一個構造函數) – CMS

+0

@ Claudiu - 在這種情況下Object.create被設置爲'function()',它不會將原型分配給任何變量。 – dopatraman

1

此代碼是不支持Object.create,這是在2009年11月

發佈的ECMAScript 5標準中規定的舊的JavaScript實現許多人說創建對象的首選方法是在創建時爲其指定一個原型。這可以稱爲differential inheritanceprototypal inheritance。事實上,這正是Object.create做:

var protoCircle = {x: 0, y: 0, radius: 1, color:"black"}; 
var myCircle = Object.create(protoCircle); 
myCircle.x = 3; 
myCircle.color = "green"; 

這使得在(3,0)爲中心半徑爲1的綠色圓圈。

原因的代碼是如此複雜,之前Object.create加入JavaScript,以便設置對象的原型唯一途徑是與new操作創建它。使用new創建的對象獲得了構造函數的prototype屬性的值作爲其原型。這絕對是令人困惑的,但prototype屬性不是對象的原型。給定一個函數對象f,f.prototype是將被指定爲通過new f()構造的所有對象的原型的對象。一個對象的真實原型被稱爲[[prototype]]__proto__,但不能在標準ECMAScript中訪問它們。令人困惑,呃?

作爲一個側面說明。 ES5規格比Crockford定義的規格更具有增強的Object.prototype規格。它需要第二個對象來配置正在定義的對象的屬性。