简体   繁体   中英

Why `void 0` could be “faster” than `undefined`?

Just lurking over weird and fancy stuff at 140byte docs and found this :

void 0 is faster than undefined but longer than the alternatives.

I lazy checked right in the Chrome console like this:

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

vs.

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

And found no difference. Maybe my lazy check is too lazy, or just the statement about the slowness isn't relevant anymore.

I'm just wondering about the JS engines internals and how it could be possible? How can we talk about the speed of primitives and operators? Is it correct and relevant? It sounds a little bit odd to me.

I'm just wondering about the JS engines internals and how it could be possible? How can we talk about the speed of primitives and operators? Is it correct and relevant? It sounds a little bit odd to me.

Yes, it's possible. undefined is a global variable, not a keyword. That means it can be shadowed. So in order to find its value, the JavaScript engine is required to walk through the scope chain and check for an "undefined" binding at each and every scope level. So for instance:

function outer() {
    function middle() {
        function inner() {
            console.log(undefined);
        }
        inner();
    }
    middle();
}
outer();

That reference inside inner requires that the JavaScript engine check the inner function's execution context's binding object, then the middle 's, then outer 's, before finally finding it at the global level. (Of course, JavaScript engines can optimize that if it seems reasonable to do so.)

In contrast, void is a keyword for the void operator and 0 is a literal, so void 0 requires no scope chain traversal. Since the void operator is defined as always returning undefined , there's a mechanism for it to perform better than the undefined global.

Not that it's likely to matter. You're more likely doing other things that will impact your performance.

FWIW, a naive benchmark:

 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(); 
 WARNING: THIS MAY LOCK UP YOUR BROWSER WINDOW. For me, it runs fine on recent Chrome, taking about 20 seconds; YMMV. 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM