2012-02-07 64 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方法。