为什么`void 0`可能比"undefined""更快"?

Bog*_*gin 0 javascript performance

只是潜伏在140byte文档的奇怪和花哨的东西,发现这个:

void 0undefined比替代品更快但更长.

我懒得在Chrome控制台中检查,如下所示:

console.time('void');
for (let a = 0; a < 1e6; a++) {() => void 0};
console.timeEnd('void');
Run Code Online (Sandbox Code Playgroud)

console.time('undefined');
for (let a = 0; a < 1e6; a++) {() => undefined};
console.timeEnd('undefined');
Run Code Online (Sandbox Code Playgroud)

并没有发现任何区别.也许我的懒惰检查太懒了,或者只是关于缓慢的陈述不再相关.

我只是想知道JS引擎内部以及它是如何可能的?我们怎样才能谈论原语和运算符的速度?它是否正确且相关?这对我来说听起来有点奇怪.

T.J*_*der 6

我只是想知道JS引擎内部以及它是如何可能的?我们怎样才能谈论原语和运算符的速度?它是否正确且相关?这对我来说听起来有点奇怪.

是的,这是可能的.undefined是一个全局变量,而不是关键字.这意味着它可以被遮蔽.因此,为了找到它的值,JavaScript引擎需要遍历作用域链并检查"undefined"每个作用域级别的绑定.例如:

function outer() {
    function middle() {
        function inner() {
            console.log(undefined);
        }
        inner();
    }
    middle();
}
outer();
Run Code Online (Sandbox Code Playgroud)

内部引用inner要求JavaScript引擎在最终在全局级别找到它之前检查inner函数的执行上下文的绑定对象,然后是middle's,然后是outer'.

相反,它voidvoid运算符的关键字,0是一个文字,因此void 0不需要范围链遍历.由于void运算符被定义为始终返回undefined,因此有一种机制使其比undefined全局运行得更好.

并不是说它可能很重要.你更有可能做其他会影响你表现的事情.

FWIW,一个天真的基准:

var x = undefined;

var now = performance && performance.now ? performance.now.bind(performance) : Date.now.bind(Date);

function outermost() {
  var a = Math.random();
  function outer() {
    var b = Math.random();
    function inner() {
      var c = Math.random();
      function test1() {
        if (Math.random() > 1) { // Never true
          x = 42;
        }
        return x == undefined;
      }

      function test2() {
        if (Math.random() > 1) { // Never true
          x = 42;
        }
        return x == void 0;
      }

      function test(f, n) {
        var start = now();
        while (n-- > 0) {
          f();
        }
        return now() - start;
      }

      console.log("Testing...");
      setTimeout(function() {
        test(test1, 100000000); // warmup
        test(test2, 100000000); // warmup
        console.log("undefined", test(test1, 1000000000), "ms");
        console.log("void 0   ", test(test2, 1000000000), "ms");
      }, 40);

      if (a + b + c > Infinity) {
        console.log("Impossible, just making sure to use a, b, and c");
      }
    }
    inner();
  }
  outer();
}
outermost();
Run Code Online (Sandbox Code Playgroud)
WARNING: THIS MAY LOCK UP YOUR BROWSER WINDOW.
For me, it runs fine on recent Chrome, taking about 20 seconds; YMMV.
Run Code Online (Sandbox Code Playgroud)

  • 是的,我知道这不是一个可以找到任何有用的性能调整的地方。这对我来说是一种“深奥”的功能。不管怎样,你的答案就是我所寻找的,谢谢! (2认同)