! + [] === true
有人可以解释这里发生了什么吗?我知道这是不正常的,但是当似乎在数学运算中使用运算符代替变量时,我正在努力理解编译器正在做什么。
更多关于这种奇怪的例子:
(! + '') === (!'')
但是
(! + []) !== (![])
答案 0 :(得分:0)
JavaScript始终将输入转换为基本类型。因此,在您使用! + []
的情况下,它将尝试将+[]
转换为字符串。将会是""
,然后由于!
而将其转换为boolean
。在JavaScript ""
中被视为false
。因此最终它将返回!false
的{{1}}。
编辑1
正如@mhodges在下面评论。 true
转换为[]
的字符串,然后""
会将其转换为+
,因此它将变为number
。
您可以从此处了解有关对象到基本体的更多信息。 object to primitive
您可以在下面检查行为。
0
答案 1 :(得分:0)
首先,重要的是要知道正在使用什么运算符,以什么顺序使用。当不清楚时,一种简单的查找方法是查看语法解析器从中解析出的内容,例如使用https://astexplorer.net/,第一个示例显示:
! + [] === true
使用一元逻辑非(!
),一元加号(+
),为空的数组文字([]
),严格相等({{1 }})和true(===
)关键字。
执行顺序为true
,或看成一棵树:
(!(+[])) === true
接下来要了解的是,每个运算符都将其操作数转换为什么。当您想详细了解时,这有点乏味。
我假设您知道一个空数组文字或 ===
/ \
! true
|
+
|
[]
会产生什么。严格的平等true
也可能因为没有太多不直观的方面而广为人知(与拥有很多的宽松平等===
相反)。因此,只有一元+和一元逻辑不相关的步骤。
根据操作顺序,我们首先来看unary +,其中==
为操作数。它对操作数执行ToNumber
,对于像我们的示例[]
这样的对象,该操作数执行[]
,后跟另一个ToPrimitive
。 ToNumber
将尝试ToPrimitive
(不会返回原语,因此不会被使用),然后尝试valueOf
。后者针对数组,搜索函数toString
并在不带参数的情况下调用该函数(将数组设置为join
)。对于空数组,这将导致空字符串this
,随后的第二次""
调用会将其转换为0
。
接下来是unary logical not,它首先用ToBoolean
转换任何操作数。这个中间步骤导致我们的操作数ToNumber
的{{1}}。然后,按预期方式,将返回相反的内容(false
)。
据我们所知,0
最后但至少是true
。
此处有趣的旁注是在默认情况下使用true === true
。我希望许多人会感到惊讶,为什么更改true
会影响结果:
Array.prototype.join
其他示例以类似的方式工作:
join
几乎相同,只是console.log(! + [] === true);
let x = [];
x.join = () => "1";
console.log(! + x === true);
Array.prototype.join = () => "1";
console.log(! + [] === true);
甚至不需要先前的(! + '')
对于ToNumber
,空字符串的ToPrimitive
为(!'')
,因此导致ToBoolean
对于false
,任何对象的true
是(![])
,导致ToBoolean