对于 Javascript 中的嵌套对象,{} 消耗的内存是否少于 []?
Does {} consume less memory than [] for nested objects in Javascript?
我有一些遗留的 JS 代码用 [] 创建了一个巨大的嵌套对象结构。
代码是这样的
var data = [];
data ["first"] = [];
data ["first"]["second"] = [];
data ["first"]["second2"] = "hello";
大约是 javascript 的 250+ KB,相当大。当我尝试用 requirejs 包装它以加载到另一个 requirejs 模块时,它抛出内存不足错误。
如果我在使用 [] 的地方使用 {},错误就会消失。
我在周末做了一些关于 [] 与 {} 的作业,原因似乎是使用关联数组作为嵌套字典在 Javascript 中可能存在漏洞,因为数组扩展了一个 JS 对象并且可能有将新对象附加到其中时会进行更多更新。但它能解释内存消耗问题吗?或者与Requirejs如何解析模块的对象有关?
我对 JS 内存检测的了解不够,在浏览器引擎中使用 {} 或 [] 进行比较,因此很难得出结论。欢迎任何关于如何检测 {} 与 [] 的提示或建议。
更新: 我昨天通过节点尝试了一些 sizeOf() 。我使用了所有现有的:"js-sizeof"、"object-sizeof"、"sizeof"
代码:
var sizeof = require('object-sizeof');
var obj = [];
obj['ball'] = 'hello';
obj['air'] = 'hello';
obj['ball']['fire'] = 'world';
obj['ball']['ice'] = [];
console.log(sizeof(obj));
var obj2 = {};
obj2['ball'] = 'hello';
obj2['air'] = 'hello';
obj2['ball']['fire'] = 'world';
obj2['ball']['ice'] = [];
console.log(sizeof(obj2));
结果是
[]: 34
{}: 34
sizeOf 实际上是相同的。,但也许 [] 发生了其他事情,可能会触发内存不足问题。我不确定是 requirejs 解析它触发了它还是某些 V8 优化路径。我认为 Lint 工具甚至不建议反对这种做法,因此在实践中 "right" 方式是哪种方式相当含糊
JavaScript 中没有 "associated array" 这样的东西。 [ 1, 2, 3 ]
是数组字面量语法;它初始化一个数组。 { foo: "bar" }
是对象字面量语法;它初始化一个对象。然而,JavaScript 的一个怪癖是数组也恰好是对象,这就是为什么这段代码 "works":
var data = [];
data["first"] = [];
data["first"]["second"] = [];
...但你不应该这样做,因为它没有任何意义。您正在初始化一个空数组 ([]
),但是您并没有像使用数组一样使用它——而是像使用对象一样使用它。如果您使用 属性 名称(data["first"]
,相当于 data.first
)而不是整数键(data[0]
),那么您需要使用对象。当您要像使用对象一样使用数组时,没有任何情况应该初始化它。
根据经验,如果您需要每个项目都有一个名称,或者需要能够通过名称快速访问它们,请使用对象 ({}
) 并使用字符串作为键。如果您需要能够按顺序迭代项目,请使用带有整数的数组作为键。
我不知道你的内存不足错误的确切原因——尤其是在没有看到你的实际代码的情况下——但你肯定应该使用对象 ({}
) ,而不是数组 ([]
) 当您不使用整数键时。 JavaScript 引擎会尽其所能进行优化,数组和对象也不例外,因此当您以引擎不期望的方式使用数组时,可能会导致性能或内存问题,这并不奇怪。
P.S。作为风格问题,在处理对象时考虑使用 属性 符号(或 "dot notation," 即 foo.bar
)而不是下标符号(即 foo["bar"]
):
var data = {};
data.first = {};
data.first.second = {};
data.first.second2 = "hello";
这与您发布的代码完全相同,但它更易于阅读,并且可能有助于您记住对象和数组有不同的用途。您也可以将其表示为单个对象文字:
var data = {
first: {
second: {},
second2: "hello"
}
};
这也完全相同,可以帮助您查看对象的 "structure"(只要您遵守缩进规范)。
大多数 JavaScript 风格指南都说你应该总是使用 "dot notation" 除非你有会导致语法错误的键。例如,如果你有一个名为"foo/bar"
的属性,你显然不能这样做:
var obj.foo/bar = 1;
...因为这是语法错误。所以你必须这样做:
var obj["foo/bar"] = 1;
...完全正确。这些情况往往是例外,所以我鼓励始终使用点符号,除非您必须使用下标符号。
我有一些遗留的 JS 代码用 [] 创建了一个巨大的嵌套对象结构。 代码是这样的
var data = [];
data ["first"] = [];
data ["first"]["second"] = [];
data ["first"]["second2"] = "hello";
大约是 javascript 的 250+ KB,相当大。当我尝试用 requirejs 包装它以加载到另一个 requirejs 模块时,它抛出内存不足错误。
如果我在使用 [] 的地方使用 {},错误就会消失。
我在周末做了一些关于 [] 与 {} 的作业,原因似乎是使用关联数组作为嵌套字典在 Javascript 中可能存在漏洞,因为数组扩展了一个 JS 对象并且可能有将新对象附加到其中时会进行更多更新。但它能解释内存消耗问题吗?或者与Requirejs如何解析模块的对象有关?
我对 JS 内存检测的了解不够,在浏览器引擎中使用 {} 或 [] 进行比较,因此很难得出结论。欢迎任何关于如何检测 {} 与 [] 的提示或建议。
更新: 我昨天通过节点尝试了一些 sizeOf() 。我使用了所有现有的:"js-sizeof"、"object-sizeof"、"sizeof"
代码:
var sizeof = require('object-sizeof');
var obj = [];
obj['ball'] = 'hello';
obj['air'] = 'hello';
obj['ball']['fire'] = 'world';
obj['ball']['ice'] = [];
console.log(sizeof(obj));
var obj2 = {};
obj2['ball'] = 'hello';
obj2['air'] = 'hello';
obj2['ball']['fire'] = 'world';
obj2['ball']['ice'] = [];
console.log(sizeof(obj2));
结果是
[]: 34 {}: 34
sizeOf 实际上是相同的。,但也许 [] 发生了其他事情,可能会触发内存不足问题。我不确定是 requirejs 解析它触发了它还是某些 V8 优化路径。我认为 Lint 工具甚至不建议反对这种做法,因此在实践中 "right" 方式是哪种方式相当含糊
JavaScript 中没有 "associated array" 这样的东西。 [ 1, 2, 3 ]
是数组字面量语法;它初始化一个数组。 { foo: "bar" }
是对象字面量语法;它初始化一个对象。然而,JavaScript 的一个怪癖是数组也恰好是对象,这就是为什么这段代码 "works":
var data = [];
data["first"] = [];
data["first"]["second"] = [];
...但你不应该这样做,因为它没有任何意义。您正在初始化一个空数组 ([]
),但是您并没有像使用数组一样使用它——而是像使用对象一样使用它。如果您使用 属性 名称(data["first"]
,相当于 data.first
)而不是整数键(data[0]
),那么您需要使用对象。当您要像使用对象一样使用数组时,没有任何情况应该初始化它。
根据经验,如果您需要每个项目都有一个名称,或者需要能够通过名称快速访问它们,请使用对象 ({}
) 并使用字符串作为键。如果您需要能够按顺序迭代项目,请使用带有整数的数组作为键。
我不知道你的内存不足错误的确切原因——尤其是在没有看到你的实际代码的情况下——但你肯定应该使用对象 ({}
) ,而不是数组 ([]
) 当您不使用整数键时。 JavaScript 引擎会尽其所能进行优化,数组和对象也不例外,因此当您以引擎不期望的方式使用数组时,可能会导致性能或内存问题,这并不奇怪。
P.S。作为风格问题,在处理对象时考虑使用 属性 符号(或 "dot notation," 即 foo.bar
)而不是下标符号(即 foo["bar"]
):
var data = {};
data.first = {};
data.first.second = {};
data.first.second2 = "hello";
这与您发布的代码完全相同,但它更易于阅读,并且可能有助于您记住对象和数组有不同的用途。您也可以将其表示为单个对象文字:
var data = {
first: {
second: {},
second2: "hello"
}
};
这也完全相同,可以帮助您查看对象的 "structure"(只要您遵守缩进规范)。
大多数 JavaScript 风格指南都说你应该总是使用 "dot notation" 除非你有会导致语法错误的键。例如,如果你有一个名为"foo/bar"
的属性,你显然不能这样做:
var obj.foo/bar = 1;
...因为这是语法错误。所以你必须这样做:
var obj["foo/bar"] = 1;
...完全正确。这些情况往往是例外,所以我鼓励始终使用点符号,除非您必须使用下标符号。