使用运算符作为变量会得出奇怪的结果

时间:2018-07-05 16:51:59

标签: javascript

! + [] === true

有人可以解释这里发生了什么吗?我知道这是不正常的,但是当似乎在数学运算中使用运算符代替变量时,我正在努力理解编译器正在做什么。

更多关于这种奇怪的例子:

(! + '') === (!'')

但是

(! + []) !== (![])

2 个答案:

答案 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,对于像我们的示例[]这样的对象,该操作数执行[],后跟另一个ToPrimitiveToNumber将尝试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