Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/366.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 使用运算符作为变量会产生奇怪的结果_Javascript - Fatal编程技术网

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);