Javascript 使用运算符作为变量会产生奇怪的结果
有人能解释一下这里发生了什么吗?我知道这是不正常的,但我很难理解编译器在数学运算中用运算符代替变量时在做什么 更多这种奇怪的例子:Javascript 使用运算符作为变量会产生奇怪的结果,javascript,Javascript,有人能解释一下这里发生了什么吗?我知道这是不正常的,但我很难理解编译器在数学运算中用运算符代替变量时在做什么 更多这种奇怪的例子: ! + [] === true 但是 JavaScript总是将输入转换为基本类型。所以在你的!+[]它将尝试将+[]转换为字符串。这将是”,然后因为它将转换为布尔值。在JavaScript 中,“”被认为是 false 。所以最终它将返回!false将成为true 编辑1 正如@mhodges在下面所评论的那样[]将转换为字符串为”,然后+将其转换为数字,因此它
! + [] === true
但是
JavaScript总是将输入转换为基本类型。所以在你的
!+[]
它将尝试将+[]
转换为字符串。这将是”
,然后因为代码>它将转换为布尔值
。在JavaScript <代码>中,“”被认为是<代码> false 。所以最终它将返回!false
将成为true
编辑1
正如@mhodges在下面所评论的那样<代码>[]
将转换为字符串为”
,然后+
将其转换为数字
,因此它将变为0
您可以从这里了解有关对象到基本体的更多信息。
您可以在下面检查行为。
var emptyBrackets=[].toString();
//转换为字符串。
log(emptyBrackets='');
//转换成数字。
控制台日志(+清空支架);
//转换为布尔值。
控制台日志(!0)代码>首先,重要的是要知道使用了哪些运算符以及它们的顺序。当这一点不清楚时,一个简单的方法是查看语法分析器从中得到了什么,例如使用,这在第一个示例中显示:
!+[]==true
使用一元逻辑not(!
)、一元加(+
)、空数组文本([]
)、严格相等(==
)和true的关键字(true
)
执行顺序为(!(+[])===true
,或视为一棵树:
(! + []) !== (![])
接下来要了解的是,每个运算符将其操作数转换为什么。当你想知道细节时,这有点乏味
我假设您知道空数组literal或true
产生什么。严格相等也可能是已知的,因为它没有太多不直观的方面(与松散相等相反,松散相等有很多方面)。因此,相关的只是一元+和一元逻辑not的步骤
给定操作顺序,我们首先将[]
作为操作数。它在操作数上执行,对于像我们的示例[]
这样的对象,操作数执行ToPrimitive
,然后执行另一个ToNumber
ToPrimitive
将尝试valueOf
(它不会返回原语,因此不会获取),然后是toString
。后者,对于数组,搜索函数join
,并在没有参数的情况下调用它(将数组设置为this
)。对于空数组,这将导致空字符串“
,通过以下第二次调用ToNumber
将其转换为0
下一个是,它首先将任何操作数转换为。此中间步骤导致操作数0
的false
。然后,正如预期的那样,将返回相反的结果(true
)
最后但最不重要的是,我们知道,true===true
的计算结果为true
这里一个有趣的旁注是在默认情况下使用Array.prototype.join
。我希望很多人会感到惊讶,为什么对join
的更改会影响结果:
===
/ \
! true
|
+
|
[]
其他示例的工作方式类似:
(!+“”)
几乎是一样的,只是ToNumber
甚至不需要前面的ToPrimitive
- 对于
(!“”)
,空字符串的ToBoolean
为false
,因此导致true
- 对于
(![])
,任何对象的ToBoolean
为true
,导致false
这样读:!(+[])
。我建议你把所有的例子都加进去,看看什么操作符是按什么顺序使用的,这里没有的是操作符被用作变量。像[]
和{}
这样的东西在任何表达式上下文中都是值,就像3
和true
一样。操作符像==
,“代码>”等被用作运算符。@AsdGerte的评论对我来说很有意义。我应该把它理解为(+[]),它强制一个对象->字符串->数字。这里不是用+
转换成数字吗<代码>+“”==0
,然后!0===true
@Keatinge我认为你部分正确。我认为Karan是对的,正如你所说,[]在被+
强制转换成一个数字之前被转换成”
。这个答案中非常重要的缺失部分是+
被用来强制“
转换成一个数字(0
)。说“它将尝试将+[]
转换为字符串”是完全错误的。@mhodges这里所讨论的所有强制都是因为+
而发生的,但是,是的,在内部,它将被强制为字符串,然后再被强制为数字。文本暗示了+[]==”
,但这完全是错误的(除了其他几个格式不太好的部分外,请参见“JavaScript始终将输入转换为基本类型”-什么?)。“我不明白为什么这一点会被高估。”卡兰·克洛斯,仍然不完全准确。JavaScript中没有int
这样的东西——它是一种Number
类型。强制数组(通过+
)将在内部调用空数组上的.toPrimitive()
,将其转换为它的(空字符串),然后将其强制为带有+
的数字。这是一个语义学的问题,但是对于这样的问题,语义学是非常重要的
===
/ \
! true
|
+
|
[]
console.log(! + [] === true);
let x = [];
x.join = () => "1";
console.log(! + x === true);
Array.prototype.join = () => "1";
console.log(! + [] === true);