Fis*_*ter 35 javascript performance
我想保留一个字符串列表,我只会检查它是否存在,例如:
corporatePlan = [
    'canDeAuthorize',
    'hasGmailSupport',
    'canShareReports',
    'canSummonKraken',
    'etc'
]
因此,当用户试图召唤海妖时,我会corporatePlan.indexof('canSummonKraken') != -1看看他是否可以.
同事建议将它作为对象存储会更快:
"Corporate Plan" = {
    'canDeAuthorize' : null,
    'hasGmailSupport' : null,
    'canShareReports' : null,
    'canSummonKraken' : null,
    'etc' : null
}
并且只'canSummonKraken' in corporatePlan需要检查计划是否包含该密钥.这在经典的CS意义上是有意义的,因为当然"包含"是地图上的恒定时间和数组上的线性.这会检查数组和对象是如何在JS中引入的吗?
在我们的特殊情况下,使用少于100个元素,速度并不重要.但是对于更大的阵列,访问哪种方式会更快?
T.J*_*der 27
在JavaScript中,您通常需要处理各种各样的实现(除非您在受控环境中使用它,例如您选择引擎的服务器),因此特定性能问题的答案往往是"它取决于,检查你将要使用的引擎." 在一个实现上最快的可能在另一个实现上更慢等等.http://jsperf.com对于这类事情很方便.
那就是说,我希望in在这里成为一个明显的赢家.Array#indexOf必须在搜索中访问数组索引,并且数组索引是与任何其他属性一样的属性.因此访问数组索引0以查看它是否是所需的字符串需要查找,0就像其他需要查找属性一样"canSummonKraken"(然后它必须在之后进行字符串比较).(是的,数组索引是属性.JavaScript中的数组根本不是数组.)并且indexOf可能必须在搜索期间访问多个属性,而in只需访问一个.但同样,你需要在你的目标环境中检查它以确定,一些实现可以优化具有连续索引范围的数组(但最慢的那些肯定不会,当然如果你担心速度,你我担心最慢的引擎上的速度最快,比如IE.
另请注意,并非所有JavaScript引擎都有Array#indexOf.大多数人都这样做,但仍然有一些较老的人(我看着你,微软)没有.
您还有使用in或是否使用的问题hasOwnProperty.使用in的优点是它是一个操作符,而不是函数调用; 使用hasOwnProperty的优点是它只会查看特定的对象实例,而不是它的原型(及其原型等).除非你有一个非常深刻的继承层次结构(并且你没有在你的例子中),我打赌in胜利,但记住它确实检查层次结构是有用的.
此外,请记住,"canSummonKraken" in obj在您显示的示例对象文字中将是如此,因为该对象确实具有该属性,即使该属性的值为null.你必须没有财产都在返回false.(而不是in,您可能只使用true和false并将其查找为obj.canSummonKraken.)
所以你的选择是:
你的数组方法:
corporatePlan = [
    'canDeAuthorize',
    'hasGmailSupport',
    'canShareReports',
    'canSummonKraken',
    'etc'
];
console.log(corporatePlan.indexOf("canSummonKraken") >= 0);  // true
console.log(corporatePlan.indexOf("canDismissKraken") >= 0); // false
......我不推荐.
该in方法:
corporatePlan = {
    'canDeAuthorize'  : null,
    'hasGmailSupport' : null,
    'canShareReports' : null,
    'canSummonKraken' : null,
    'etc'             : null
};
console.log("canSummonKraken" in corporatePlan);  // true
console.log("canDismissKraken" in corporatePlan); // false
可能比indexOf它快,但我会测试它.如果列表可能很长并且你将要拥有很多这些对象,那么它很有用,因为它只需要存在"truthy"属性.空对象表示用户无法执行任何操作的计划,并且非常小.
我应该在这里注意两件事:
in也检查对象的原型,所以如果你有像toString或那样的设置valueOf,你会得到误报(因为这些属性几乎都是所有对象都来自Object.prototype).在支持ES5的浏览器上,您可以通过使用null原型创建对象来避免此问题:var corporatePlan = Object.create(null);
也许是因为它检查原型,in操作员在一些引擎上出乎意料地慢.
这两个问题都可以通过使用hasOwnProperty来解决:
console.log(corporatePlan.hasOwnProperty("canSummonKraken"));  // true
console.log(corporatePlan.hasOwnProperty("canDismissKraken")); // false
有人会认为运算符比方法调用更快,但事实证明,跨浏览器并不可靠.
标志方法:
corporatePlan = {
    'canDeAuthorize'   : true,
    'hasGmailSupport'  : true,
    'canShareReports'  : true,
    'canSummonKraken'  : true,
    'canDismissKraken' : false,
    'etc'              : true
};
console.log(corporatePlan.canSummonKraken);  // "true"
console.log(corporatePlan.canDismissKraken); // "false"
// or using bracketed notation, in case you need to test this
// dynamically
console.log(corporatePlan["canSummonKraken"]);  // "true"
console.log(corporatePlan["canDismissKraken"]); // "false"
// example dynamic check:
var item;
item = "canSummonKraken";
console.log(corporatePlan[item]);  // "true"
item = "canDismissKraken";
console.log(corporatePlan[item]);  // "false"
......这是一种相当正常的方式,可能比它快in,并且可能至少和它一样快hasOwnProperty.(但请参阅我的开头段落:在您的环境中测试.:-))
onc*_*ode 15
我测试了它:http://jsperf.com/array-indexof-vs-object-s-in-operator/4
找到第一个元素时,两者都有很好的结果,具体取决于使用的浏览器.因此,找到最后一个元素,in运算符要快得多.
但后来我使用了一个带有typeof运算符的变体,它比两者都快得多:
if (typeof obj['that'] !== "undefined") {
  // found
}
Juz*_*Ali 11
这是一个基准http://jsperf.com/array-indexof-vs-object-keys.在chrome和firefox中,检查对象中键的存在比扫描数组快100%.

但是如果考虑初始化时间,差异会消除,对象会比数组花费更多时间进行初始化.

| 归档时间: | 
 | 
| 查看次数: | 17540 次 | 
| 最近记录: |