2012-02-07 78 views
6

我正在嘗試將數組對象聲明爲數組對象,並發現JSON.stringify未正確處理數組類對象時,它被定義爲數組對象。Javascript數組對象與數組像對象 - 澄清

,請參閱下文更加清晰, - >jsFiddle

var simpleArray = []; //note that it is defined as Array Object 

alert(typeof simpleArray); // returns object -> Array Object 

simpleArray ['test1'] = 'test 1'; 
simpleArray ['test2'] = 'test 2'; 

alert(JSON.stringify(simpleArray)); //returns [] 

它能正常工作並返回我{"test1":"test 1","test2":"test 2"}當我改變

var simpleArray = [];var simpleArray = {};

有人可以提供一些燈光或一些參考,我可以閱讀更多?

編輯:

問題:當typeof運算simpleArray = []simpleArray = {}返回的對象,爲什麼JSON.stringify不能夠在這兩種情況下返回{"test1":"test 1","test2":"test 2"}

回答

2

你不想要一個數組。當你想在JavaScript中使用「關聯數組」時,你真的需要一個對象,{}

你可以用instanceof Array區分:

[] instanceof Array // true 
({}) instanceof Array // false 

編輯:它可以處理它。它序列化數組的所有元素。但是,要成爲一個元素,必須有一個數字鍵。在這種情況下,沒有。

這對JSON來說並不是特有的。這符合toSourcelength財產。

+0

我明白那部分,我想知道的是爲什麼JSON.stringify在聲明爲[]時無法處理。 – 2012-02-07 21:46:29

+0

謝謝!我正在尋找instanceof。我正在嘗試使用typeof,它在兩種情況下都返回對象。 – 2012-02-07 21:53:12

+1

由於ES 5還有'Array.isArray(...)'(15.4.3.2),相反,它是框架安全的。它可以被模擬。 – PointedEars 2012-02-07 22:14:14

4

區別在於指標。當您使用數組[]時,索引只能是正整數。

所以下面是錯誤的:

var array = [ ]; 
array['test1'] = 'test 1'; 
array['test2'] = 'test 2'; 

因爲test1test2不是整數。爲了解決這個問題,你需要使用基於整數索引:

var array = [ ]; 
array[0] = 'test 1'; 
array[1] = 'test 2'; 

,或者如果你聲明一個JavaScript對象,然後屬性可以是任意的字符串:

var array = { }; 
array['test1'] = 'test 1'; 
array['test2'] = 'test 2'; 

這相當於:

var array = { }; 
array.test1 = 'test 1'; 
array.test2 = 'test 2'; 
+0

那麼當你做'var simpleArray = []; simpleArray ['test2'] ='測試2';'? – 2012-02-07 21:43:37

+3

@MattFenwick,會發生什麼情況與您所期望的相反:'simpleArray.length = 0'這意味着此數組中沒有元素。你仍然可以使用'simpleArray.test2'來訪問你定義的屬性。這只是應該避免的混淆代碼。 – 2012-02-07 21:45:55

+0

+1的詳細解釋,但是,我想知道的是爲什麼JSON.stringify聲明爲[]時無法處理。我試圖使用typeof,並在兩種情況下返回對象。我將把這添加到我的問題中。 – 2012-02-07 21:51:09

1

JSON.stringify遇到一個數組時,它將以類似的方式迭代從0simpleArray.lengthfor循環以找到這些值。例如:

var a = []; 
a[5] = "abc"; 
alert(JSON.stringify(a)); // alerts [null,null,null,null,null,"abc"] 

因此,對它設置屬性對於JSON來說是完全不可見的。

但是,使用{}來定義對象會使JSON將其視爲一個對象,因此它將遍歷對象的屬性(不包括來自原型鏈的繼承屬性)。通過這種方式,它可以找到您的test1test2屬性,併成功返回您的預期。

2

「有人可以提供一些燈光或一些參考,我可以閱讀更多?

當你處理JSON數據,你可以參考json.org閱讀有關規範的要求。

JSON中,Array是由,分開的值的順序列表。

enter image description here

所以JSON.stringify()是根本無視任何不能被表示爲一個簡單的排序列表。

所以,如果你這樣做......

var simpleArray = []; 
simpleArray.foo = 'bar'; 

...你還是給一個數組,所以它期待只有數字指標,而忽略了其他任何東西。

由於JSON與語言無關,因此使用JSON的方法需要決定哪種語言結構最適合每個JSON結構。

所以JSON具有以下結構...

{} // object 
[] // array 

你應該注意到,雖然看起來非常相似,JavaScript對象和數組,他們是不完全一樣。

任何JavaScript用於創建JSON結構的結構必須符合JSON結構允許的結構。這就是爲什麼非數字屬性被刪除排除。

雖然JavaScript不介意他們,JSON將不會容忍他們。

+0

非數字屬性(更好:具有非數字*名稱*的屬性)不會被刪除。他們不考慮迭代。 – PointedEars 2012-02-07 22:25:45

+0

@PointedEars:這句話很差。我的意思是,作爲開發人員的角度去掉,如*「嘿,他們在我的數組對象,但不是在我的JSON文本!」*。我應該說*「排除」*。 – 2012-02-07 22:37:55

-1

您的代碼在語義上並不正確,但由於大多數JavaScript引擎對程序員非常好,他們允許這些類型的錯誤

簡單的測試案例:

var a = []; 
a.b = "c"; 
console.log(JSON.stringify(a));//yields [], and not {"b":"c"} as you might expect 

這可能是因爲在JSON.stringify一些嚴厲仍然把aArray的。 我不會擔心它太多。這是你的程序中不應該發生的情況,因爲它是一個錯誤。 JSLint是一種在您的代碼中捕獲這些以及更多潛在問題的流行工具。

+0

祈禱告訴,*語法*有什麼問題? – PointedEars 2012-02-07 22:00:50

+0

我認爲這很明顯:你不能在'Array'中聲明字符串鍵。僅僅因爲大多數JavaScript引擎都接受它並不能使它成爲_correct_。我希望你認爲倒票是值得的。 – Halcyon 2012-02-07 22:46:48

+0

您對JavaScript的本質,ECMAScript對象的屬性以及屬於編程語言的語法有着嚴重的誤解。一個評論是簡短的。 *沒有鍵。*對象具有*屬性*名稱。屬性名稱是* strings *,可以用'['...']','.'或隱式(範圍鏈)訪問。 JavaScript是一個ECMAScript實現。 * JavaScript *只有兩種生產質量的「實現」:SpiderMonkey和Rhino;其他像JScript是* ECMAScript *實現。待續... – PointedEars 2012-02-08 11:15:20

0

在Javascript中,一切都是一個對象,所以即使是數組。 這就是爲什麼你會得到:

>> var l = [1, 2]; 
>> typeof l 
"object" 

陣列的存儲方式爲對象相同。所以,實際上,數組只是散列表對象。您在訪問時提供的索引

>> l[0] 

不被解釋爲偏移量,而是被散列,然後搜索。

所以,數組只是對象(帶有一些內置的數組方法),因此您可以像對象一樣對待它們並在某個特定的關鍵點下放置一個值。 但是隻有那些以數字索引的鍵被用來計算長度。

>> var l = [] 
>> l.length 
0 
>> l[5] = 1; 
>> l.length 
6 
>> l 
[undefined, undefined, undefined, undefined, undefined, 1] 
>> l.hello = "Hello" 
>> l.length 
6 

Array - MDN爲什麼你不應該這樣做的更多信息 和Associative Arrays considered harmful

+0

不*所有*都是一個對象。有原始的價值。但沒有「Javascript」,有幾種不同的ECMAScript實現。 – PointedEars 2012-02-07 22:02:23

1

Array實例與其他對象之間的差異在ECMAScript Language Specification, Edition 5.1的第15.4節中指定。

你會發現那裏,雖然你可以使用支架屬性訪問的語法與所有對象引用 -

objRef[propertyName] 

- Array情況是特殊的。僅使用一個參數值,該值表示的是小於2的無符號32位整數值的字符串表示形式訪問封裝陣列結構的元素,並且寫入訪問會影響實例的length屬性的值。

第15.12節規定了JSON對象及其相應的stringify方法。