簡體   English   中英

Object.create(Object.prototype),Object.create(Object)和Object.create(null)之間的區別

[英]difference between Object.create(Object.prototype) , Object.create(Object) and Object.create(null)

我應該為其他人繼承的第一個父對象傳遞哪個參數,哪個參數更有效

Object.create(Object.prototype)

Object.create(Object)

Object.create(null)  

Object.create(null)返回一個空對象

Object.create(Object)返回一個函數為什么????(我檢查了我的日志,它說的是函數...我使用了console.dir())

Object.create(Object)返回一個非空對象

這一切是如何工作的......我更習慣於Classname .prototype的東西:(

無法理解這里發生了什么

前言:JavaScript使用原型繼承,這意味着一個對象可以擁有(通常有)一個原型 ,它是另一個對象。 如果您嘗試從它沒有的對象獲取屬性的值,JavaScript引擎會查找對象的原型(及其原型等)以查找它。

Object.create創建對象。 您給Object.create的第一個參數是用作它創建的對象的原型的對象。 所以:

// Create an object with a property 'foo'
var a = {
    foo: 42
};

// Create a blank object using `a` as its prototype
var b = Object.create(a);

// Give `b` a property of its own
b.bar = "hi";

這讓我們記憶猶新:

+−−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−−−−−−−+
                           | [[Prototype]] |−−−−−>| (the standard     |
a−−−−−−−−−−−−−−−−−−−−−−+−−>| foo: 42       |      | object prototype) |
                       |   +−−−−−−−−−−−−−−−+      +−−−−−−−−−−−−−−−−−−−+   
                       |
    +−−−−−−−−−−−−−−−+  |
b−−>| [[Prototype]] |−−+
    | bar: "hi"     |
    +−−−−−−−−−−−−−−−+

證明b使用a

console.log(b.foo); // 42
a.foo = 67;
console.log(b.foo); // 67

解決一些變化:

var o = Object.create(Object.prototype);

這與var o = {};完全相同var o = {}; :它創建一個新的空白對象,其原型是對象Object.prototype引用。

var o = Object.create(Object);

這會創建一個新的空白對象o其原型是Object函數。 它不會創建一個函數,只是一個具有函數作為其原型的非函數對象。 這可能很奇怪,可能不是你想要的。 :-)

var o = Object.create(null);

創建一個新的空白對象o其原型為null 由於它的原型是null ,它沒有通常的Object.prototype東西,比如toStringvalueOf以及hasOwnProperty 這有點不尋常,雖然有一些用例,例如當你使用一個對象作為字典/地圖而不想要那些屬性名稱的誤報時。 (在ES2015 [aka ES6]中,另一種選擇是使用Map代替。)


正如thg435在下面的評論中指出的那樣,關於JavaScript的一個令人困惑的事情是,對象的prototype您在函數上看到的prototype屬性完全不同。 如果prototype屬性有一個不同的名稱可能會更好(雖然我無法想象沒有大規模笨重的名稱)。

一個對象(我們稱之為o )有一個繼承屬性的原型對象。 (在ES2015 +中,您可以通過Object.getPrototypeOf訪問該對象。)函數的prototype屬性上的對象不一定是任何對象的原型。 相反,它是將被指定為通過new使用該函數創建的任何對象的原型的對象。

這里有例子幫助。

function Foo() {
}

該函數Foo具有引用對象的屬性Foo.prototype 那個對象還沒有用作任何東西的原型。 它只是一個分配給Foo對象實例上名為prototype的屬性的對象。

var f = new Foo();

現在該對象被用作原型,特別是它是new Foo調用創建的f對象的原型。

忽略一些細節,這行代碼:

var f = new Foo();

...基本上這樣做:

// Create a blank object, giving it `Foo.prototype` as its prototype
var f = Object.create(Foo.prototype);

// Call` Foo` using that new object as `this`
Foo.call(f);

正如我所說,這留下了一些細節,但希望它有助於明確函數的prototype屬性是什么......

返回的是一個對象。

>>> typeof Object.create(Object)
<<< "object"
>>> Object.create(Object)
<<< Function {}
//           ^^

Function是Chrome處理對象構造Function的名稱。 請參閱如何在Chrome Dev Tools中為自定義類計算javascript類名?


這部分答案解決了@ phenomnomnominal在問題中的評論,解釋了為什么創建的對象繼承了函數屬性,如call

Object構造函數是一個函數,因此繼承自Function原型:

>>> Object.call === Function.prototype.call
<<< true

因此,具有Object作為原型的Object也將通過原型鏈鏈接到Function原型:

>>> Object.create(Object).call === Function.prototype.call
<<< true

正如@TJ所提到的,使用構造函數作為原型是相當奇怪的。 您應該將對象指定為創建的對象將繼承的原型。 @TJ已經做了很好的解釋這部分的工作。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM