12

所以这是一个有趣的...当我在一个元素上测试 setAttribute 与普通属性集的性能时,我发现了一个奇怪的行为,然后我在常规对象上进行了测试......它仍然很奇怪!

因此,如果您有一个对象A = {},并且您将其属性设置为A['abc_def'] = 1, 或A.abc_def = 1,它们基本上是相同的。但是,如果你这样做A['abc-def']= 1 或A['123-def']= 1,那么你就有麻烦了。它变得更慢了。我在这里设置了一个测试:http: //jsfiddle.net/naPYL/1/。它们在除 chrome 之外的所有浏览器上都相同。有趣的是,对于“abc_def”属性,chrome 实际上比 Firefox 和 IE 快得多,正如我所料。但是对于“abc-def”,它至少慢了一倍。

所以基本上这里发生的事情(至少从我的测试中)是,当对属性使用“正确”语法时(合法的 C 语法,你可以使用点属性) - 它很快,但是当你使用需要使用括号的语法时(a [...]) 那么你就有麻烦了。

我试图想象什么实现细节会以这种方式区分两种模式,但不能。因为在我看来,如果您确实支持那些非标准名称,那么您可能会将所有名称转换为相同的机制,其余的只是编译到该机制中的语法。所以 。编译后语法和 [] 应该都是一样的。但很明显,这里有一些事情正在发生相反的情况......

不看 V8 的源代码,谁能想到一个真正令人满意的答案?(把它想象成一个练习:-))

这也是一个快速的 jsperf.com 示例

感谢 NDM 的 jsperf 示例!

编辑:

为了澄清,我当然还想从真实代码(我已经找到)中得到一个具体的答案,或者更准确地说——具体实现背后的原因。这就是我要求您将其视为“练习”的原因之一,以查看技术实现的背后并尝试找出原因。

但我也想看看其他人的思想在这种情况下是如何运作的。对你们中的一些人来说,这可能听起来“模糊”——但不时尝试像其他人一样思考,或接受他们的观点是非常有用的。它增强了你自己的思维方式。

4

1 回答 1

5

所以 JS 对象可以用于两个相互冲突的目的。它们可以用作对象,但也可以用作哈希表。然而,对于对象来说什么是快速且有意义的却不是哈希表,所以 V8 试图猜测给定的对象是什么。

用户可以给出他想要字典的一些标志是删除一个属性或给一个属性一个不能使用点符号访问的名称

还使用了其他一些启发式方法,我做了一个要点https://gist.github.com/petkaantonov/6327915

然而,有一个非常酷的 hack可以从哈希表地狱中赎回一个对象:

function ensureFastProperties(obj) {
    function f() {}
    f.prototype = obj;
    return obj;
}

在行动中看到它:http: //jsperf.com/property-dash-parformance/2

赎回的对象不如原始对象快,因为属性存储在外部属性数组中,而不是对象内。但这仍然比哈希表好得多。请注意,这仍然是一个非常糟糕的基准,不要认为哈希表只比 inobject 属性慢 2 倍。

于 2013-09-27T10:19:21.623 回答