“void 0”和“未定义”之间的区别

IT技术 javascript google-closure google-closure-compiler
2021-02-04 16:58:37

我正在使用"Closure Compiler",在编译我的脚本时,我花费了以下内容:

编译前:

// ==ClosureCompiler==
// @compilation_level SIMPLE_OPTIMIZATIONS
// @output_file_name default.js
// @formatting pretty_print,print_input_delimiter
// ==/ClosureCompiler==

var myObj1 = (function() {

  var undefined;   //<----- declare undefined

  this.test = function(value, arg1) {

    var exp = 0;
    arg1 = arg1 == undefined ? true : arg1;  //<----- use declare undefined
    exp = (arg1) ? value * 5 :  value * 10;

    return exp;
  };

  return this;
}).call({});

var myObj2 = (function() {

  this.test = function(value, arg1) {

    var exp = 0;
    arg1 = arg1 == undefined ? true : arg1;  //<----- without declare undefined
    exp = (arg1) ? value * 5 :  value * 10;

    return exp;
  };

  return this;
}).call({});

编译:

// Input 0
var myObj1 = function() {
  this.test = function(b, a) {
    a = a == void 0 ? true : a;  //<-----
    var c = 0;
    return c = a ? b * 5 : b * 10
  };
  return this
}.call({}), myObj2 = function() {
  this.test = function(b, a) {
    a = a == undefined ? true : a; //<-----
    var c = 0;
    return c = a ? b * 5 : b * 10
  };
  return this
}.call({});

有了这个我相信“void 0”和“undefined”的使用问题,使用上有什么区别还是两种情况都很好?。

编辑

如果我定义用“void 0”编译的“var undefined”,如果我没有定义用“undedined”编译的“undefined”。那么不是“undefined”和“void 0”之间的字符数问题

测试

编辑二:性能,基于此链接

代码和测试

IE 8:
typeof: 228ms
undefined: 62ms
void 0: 57ms

Firefox 3.6:
typeof:10ms
未定义:3ms
void 0:3ms

Opera 11:
typeof:67ms
未定义:19ms
void 0:20ms

Chrome 8:
typeof:3ms
未定义:5ms
void 0:3ms

4个回答

来自 MDN

void运算符计算给定的expression,然后返回undefined

此运算符允许将产生副作用的表达式插入需要计算结果为 undefined 的表达式的位置。

void 运算符通常仅用于获取undefined原始值,通常使用“ void(0)”(相当于“ void 0”)。在这些情况下,undefined可以改用全局变量(假设它没有被分配给一个非默认值)。

Closure Compiler 换入,void 0因为它包含的字符少于undefined因此产生等效的、更小的代码


回复:OP评论

是的,我阅读了文档,但在我给出的示例中,在使用“void 0”和另一个“未定义”的情况下,“谷歌关闭”

我相信这实际上是Google Closure Compiler 中的一个错误

[][0] 是另一种选择
2021-04-06 16:58:37
2021-04-13 16:58:37
是的,我阅读了文档,但在我给出的示例中,在使用“void 0”和另一个“未定义”的情况下,“谷歌关闭”
2021-04-14 16:58:37

void expr之间真正唯一的语义区别undefined是,在ECMAScript 3 上undefined全局对象属性(window.undefined在浏览器环境中)是可写的,而void 运算符将始终返回undefined

一种经常实现的流行模式,可以放心使用undefined,只需声明一个参数,而不向它传递任何内容:

(function (undefined) {
  //...
  if (foo !== undefined) {
    // ...
  }

})();

这将允许缩小器将参数缩小为单个字母(甚至比void 0:),例如:

(function (a) {
  //...
  if (foo !== a) {
    // ...
  }
})();
好的。谢谢你,我想知道这个undefinedvalue是否是一个财产。typeofnan.blogspot.com/2011/01/typeof-is-fast.html
2021-03-16 16:58:37
CMS,window.undefined = 0但是assert( 0 != undefined)我是不是错过了什么。
2021-04-05 16:58:37
谢谢!我立即检查了这一点,void 0表现比undefined现在明显好得多,但它仍然落后于缓存版本。
2021-04-08 16:58:37
我认为如果您在任何非匿名且未立即调用的函数上使用此方法,您就会遇到麻烦。如果有人使用参数调用它(在大多数情况下,将额外参数传递给函数不会影响行为,例如alert('test', '2nd param ignored')),例如通过像someFunc.apply(this, arguments)这样的代码冒着与完全不同的变量进行比较的风险。我不会依靠这种技术来保存仅 5 个字符,当 GZIP 时,这些字符很可能会更少。
2021-04-11 16:58:37
@jAndy,不错的文章,感谢您的提及;),顺便说一句,您可以添加一个针对 的测试void 0,这可能很有趣...
2021-04-12 16:58:37

只是对之前所有答案的跟进。

它们看起来一样,但对编译器来说它们是完全不同的。

这两个代码部分编译为不同的输出,因为一个是指一个局部变量(var undefined),编译器只是简单地将它内联,因为它只使用了一次并且不超过一行。如果它被多次使用,那么这种内联将不会发生。内联提供“未定义”的结果,用较短的时间表示为“void 0”。

没有局部变量的那个是指全局对象下名为“undefined”的变量,它被闭包编译器自动“extern'ed”(实际上,所有全局对象属性都是)。因此,不会发生重命名,也不会发生内联。瞧!仍然“未定义”。

没什么区别,自己试试吧:

void 0 === undefined

将评估为true.
undefined长了3 个字符,我想这就是他们以这种方式使用它的原因。

@Harry,在代码中存在巨大差异。但经过评估,双方其实都是“foo”字符串。未定义是 void 的结果。因此,即使代码中的 void 0 与 undefined 不一样,但它确实评估为 undefined,评估后为 undefined。以同样的方式,我们说“2+2 是 4”。是的,“2+2”不是 4,它的计算结果是 4,但计算后它是 4!
2021-03-18 16:58:37
因此,这是一种带宽优化:通过网络发送更少的字节?
2021-03-29 16:58:37
如果我定义了用“void 0”编译的“var undefined”,如果我没有定义用“undedined”编译的“undefined”。那么不是“未定义”和“void 0”之间的字符数问题
2021-04-03 16:58:37
@JoelCoehoorn:闭包编译器也是一个压缩器,我猜他们试图在这里压缩每个字节。
2021-04-07 16:58:37
(function () { return 'foo' })() === 'foo'也返回真。这是否意味着两者之间没有区别?
2021-04-12 16:58:37