我想保留一个字符串列表,我只会检查它的存在,例如:
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个,速度并不重要。但是对于更大的数组,哪种方式访问起来会更快?
投票
[在JavaScript中,您通常要处理各种各样的实现方式(除非您在受控环境(例如您选择引擎的服务器)中使用它),因此,针对特定性能问题的答案通常是“取决于您要使用的引擎。”一个实现上最快的执行速度可能会慢一些,以此类推。http://jsperf.com对于此类事情非常有用。
就是说,我希望in
在这里显然是赢家。 Array#indexOf
必须在搜索中访问数组索引,并且数组索引是与其他任何属性一样的属性。因此,访问数组索引0
以查看它是否是所需的字符串,需要查找0
,就像另一个需要查找属性"canSummonKraken"
一样(然后它必须随后进行字符串比较)。 (是的,数组索引是属性。JavaScriptaren't really arrays中的数组完全是。)并且indexOf
在其搜索过程中可能必须访问多个属性,而in
仅需要访问一个属性。但是同样,您需要在目标环境中进行检查,以确保某些实现可以优化具有连续索引范围的数组(但最慢的数组肯定没有,当然,如果您担心速度,可以'担心最慢的引擎(例如IE引擎)上最快的是什么。
还请注意,并不是所有的JavaScript引擎都具有Array#indexOf
。大多数都可以,但是仍然有一些旧的(我在看着你,微软)没有。
您还有使用in
还是hasOwnProperty
的问题。使用in
的优点是它是一个运算符,而不是函数调用;使用hasOwnProperty
的优点是,它将仅查看特定的对象实例,而不查看其原型(及其原型等)。除非您有一个非常深层次的继承层次结构(并且在您的示例中没有),否则我相信in
会获胜,但是记住它确实会检查层次结构很有用。
[另外,请记住,在您显示的示例对象文字中,"canSummonKraken" in obj
将为true,因为该对象确实具有属性,即使该属性的值为null。您不必具有属性[[at all才能使in返回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
快,但我会对其进行测试。如果列表可能很长,并且您将要拥有很多这样的对象,则很有用,因为它只要求“真正的”属性存在。空对象表示用户无法执行任何操作的计划,并且非常小。我应该在这里注意两件事:
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
一样快。 (但请参见我的开头段落:在您的环境中进行测试。:-))
投票
找到第一个元素时,根据所使用的浏览器,两者都有很好的结果。因此,找到最后一个元素,in
运算符要快得多。
但是后来我使用了一个带有typeof运算符的变体,它比两者都快得多:
if (typeof obj['that'] !== "undefined") { // found }
投票
但是如果考虑到初始化时间,则差异会抵消,对象比数组花费更多的时间进行初始化。
<< img src =“ https://image.soinside.com/eyJ1cmwiOiAiaHR0cHM6Ly9pLnN0YWNrLmltZ3VyLmNvbS96WGpXZC5wbmcifQ==” alt =“在此处输入图像描述”>
投票
我运行了一个简单得多的测试,该测试仅实际测试:array.indexOf
操作并与object[key]
引用和值here进行比较。
这表明,仅涉及1个键并且查找失败时,array.indexOf
运算符的速度要慢〜
6X。
这实际上是对最佳情况数据集(1个条目)的最坏情况查找(失败),应该充当大多数此类操作的良好代理。对于添加到源Array a
/ Object o
的每个键,它都会放慢速度。
Object
参考无疑是赢家。