为什么在JavaScript中“~undefined”等于-1?

22
根据这篇文章,运行以下代码
> ~function () { console.log('foo');}()
  foo
  -1

众所周知,上述匿名函数的返回值为undefined为什么~undefined等于-1?我找不到类似的问题。


6
对于像我这样的人,想知道 JavaScript 中波浪号(~)的作用,这里有答案 - Uwe Keim
3
因为JavaScript,这就是原因! - Jose Faeti
@JoseFaeti 或者因为有些人无法正确学习它,这就是原因! - zerkms
3个回答

22

~ 是按位非操作符。它使用ToNumber将参数转换为数字。 ToInt32的定义如下:

  1. 令number等于ToNumber(argument)的结果。
  2. 如果转换后的number无效,返回undefined。
  3. 如果number是NaN、+0、-0、+∞或-∞,则返回+0。
    ...

ToNumber(undefined)返回NaN,所以根据第3步,ToInt32返回0

因此,~0-1


1
请问您能指出标准在哪里说“运算符被转换为带符号的32位整数,采用二进制补码格式”吗?同时也可以提供一下 ToInt32 的链接吗?(我并不是在质疑您的答案,只是好奇而已。) - Holt
@Holt:我已经链接到 ToInt32 的定义了。你需要 NOT 运算符规范的链接吗? - Felix Kling
是的,我在这里找到了它(http://www.ecma-international.org/ecma-262/6.0/index.html#sec-bitwise-not-operator) - 标准比developer.mozilla.org上的文档更加明确,我认为在您的帖子中添加NOT运算符的标准链接(甚至引用)可能是一个好主意。 - Holt
所有的位运算符在JavaScript中都是使用(主要)带符号的32位整数完成的 - 我说“主要”,因为<<,>>的右操作数以及>>>的左右操作数都是无符号的32位。 - Jaromanda X
@JaromandaX 我之所以问这个问题是因为(对我来说)developer.mozilla.org上的引用有点暧昧,但标准明确指向 ToInt32 - Holt

7
JS中不能用位来表示的所有内容(例如"undefined, NaN")在使用位运算符~时会被视为0或者0000000000000b,因为它将操作数转换为带符号的整数。这个操作是按位非(1的补码),会翻转位,所以该语句结果为111111111111b,即一长串1。当使用二进制数字时,最高位(MSB)被视为符号。因此,将所有的0转换为1后,结果为-1,例如尝试执行~0。要获取数字的二进制表示,请使用以下代码:(-3 >>> 0).toString(2)。详见@felixkling的回答。

2
显然,undefined的位表示全部为0。可以通过以下方式看到这一点:undefined | 0,其结果为0。因此,我们知道undefined的位表示都是零。
如果我们现在反转所有位(这正是~所做的),我们得到所有的1,即-1的表示。
所有这些都是由于JavaScript的类型协同作用而实现的。

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