为什么在Javascript中使用Boolean()函数会如此缓慢?

9
根据ECMAScript规范,一元逻辑非运算符 (!)和Boolean()函数 都使用内部函数 ToBoolean(),而逻辑非运算符还进行了一些检查以反转结果。那么为什么双重逻辑非操作比运行Boolean()函数快得多呢?
我使用了下面的代码来测试哪个更快:

function logicalNotOperator() {
  var start = performance.now();
  for (var i = 0; i < 9999999; i++) !!Math.random();
  return 0.001 * (performance.now() - start);
}
 
function booleanFunc() {
  var start = performance.now();
  for (var i = 0; i < 9999999; i++) Boolean(Math.random());
  return 0.001 * (performance.now() - start);
}

var logicalNotOperatorResult = logicalNotOperator();
var booleanFuncResult = booleanFunc();
var diff = booleanFuncResult - logicalNotOperatorResult;

console.log('logicalNotOperator:', logicalNotOperatorResult);
console.log('booleanFunc:', booleanFuncResult);
console.log('diff:', diff);

注意:我指的不是new Boolean()构造函数,而是将其给定参数强制转换为布尔值的Boolean()函数。


更快 - 有证据吗? - dfsq
Boolean() 还是 new Boolean()? - StarPinkER
1
Boolean()每次调用都需要创建一个新的执行上下文,而!!true则不需要;我猜这就是花费大量时间的地方。 - Matt
抱歉,我指的是 Boolean(),当然不是 new Boolean - Qantas 94 Heavy
1
似乎 Boolean()!! 更快了。在两个不同的设备上尝试了 Chrome 86。 - Andriy Buday
2个回答

7

1
我对你关于“XOR”的说法很感兴趣,希望能够看到证据(这并不意味着我不相信你,只是想知道你从哪里得到这样的信息)。 - Christoph
http://hg.mozilla.org/integration/mozilla-inbound/file/7c905a200bcc/js/src/methodjit/FastOps.cpp#l768(这是针对JägerMonkey-Spidmonkey的JavaScript方法即时编译器的链接)。 - Ven
好的,有趣。为什么你要使用这样奇怪的测试设置呢?两个不相关函数调用的开销似乎削弱了测试结果的表现力。 - Christoph
2
这是为了避免JIT将所有东西优化掉,因为它没有副作用。 - Ven
1
它们在Chrome 75中似乎基本相等(差异约为1%)。 - Inkling

0

我不知道Javascript JIT编译器内部是如何执行的。而且现在2020年,布尔函数在Chrome中运行得更快。但如果有不同的浏览器、不同的版本或不同的JS引擎,!!运算符可能会更快。我认为我知道答案的原因。当您调用一个函数时,内存中会有额外的工作来推入堆栈和弹出堆栈。当您使用!(NOT运算符)时,无需为推入/弹出堆栈创建额外的工作。这就是为什么NOT运算符更快的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接