代码有点像这样
var data = []; data ["first"] = []; data ["first"]["second"] = []; data ["first"]["second2"] = "hello";
它大约是250 KB的javascript,相当大.当我尝试用requirejs包装它以加载到另一个requirejs模块时,它会抛出Out Of Memory错误.
如果我使用{},那么错误就会消失.
我周末在[]和{}上做了一些功课,原因似乎是使用关联数组作为嵌套词典可能在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工具甚至建议反对这种做法,所以它在实践中是“正确的”方式是相当模糊的
解决方法
var data = []; data["first"] = []; data["first"]["second"] = [];
……但是你不应该这样做,因为它没有任何意义.你正在初始化一个空数组([]),但是你没有像数组一样使用它 – 你像对象一样使用它.如果您正在使用属性名称(data [“first”],它等同于data.first)而不是整数键(data [0]),那么您希望使用Object.当您要像对象一样使用它时,不应该初始化数组.
根据经验,如果您需要每个项目都有名称,或者需要能够通过名称快速访问它们,请使用对象({})并使用字符串作为键.如果您需要能够按顺序迭代项目,请使用带有整数的数组作为键.
我不知道你的内存不足错误的确切原因 – 尤其是在没有看到你的实际代码的情况下 – 但绝对是你应该使用Object({})而不是数组([])的情况当你没有使用整数键时. JavaScript引擎可以优化它们所能提供的一切,并且Arrays和Objects也不例外,因此当您以引擎不期望的方式使用Array时可能会导致性能或内存问题并不奇怪.
附:作为一种风格问题,在处理对象时,请考虑使用属性表示法(或“点符号”,即foo.bar)而不是下标符号(即foo [“bar”]):
var data = {}; data.first = {}; data.first.second = {}; data.first.second2 = "hello";
这与您发布的代码完全相同,但它更容易阅读,可能会帮助您记住对象和数组有不同的用途.您也可以将其表达为单个对象文字:
var data = { first: { second: {},second2: "hello" } };
这也完全相同,可以帮助您查看对象的“结构”(只要您对缩进有规律).
大多数JavaScript样式指南都说您应该始终使用“点表示法”,除非您有可能导致语法错误的键.例如,如果你有一个名为“foo / bar”的属性,你显然不能这样做:
var obj.foo/bar = 1;
…因为这是一个语法错误.所以你必须这样做:
var obj["foo/bar"] = 1;
……这完全有效.这些情况往往是例外,所以我鼓励总是使用点表示法,除非你必须使用下标符号.