JavaScript 中意想不到的时刻将挑战你对该语言的理解

2025-05-25

JavaScript 中意想不到的时刻将挑战你对该语言的理解

JavaScript是世界上最流行的编程语言之一,被广泛用于构建动态交互式网站、Web 应用程序,甚至桌面和移动应用程序。JavaScript 因其广泛的应用和与各种平台的兼容性,成为了通往其他 Web 技术的门户。它已成为现代 Web 开发的基础语言。但它同时也是一种复杂的语言,其中存在许多意想不到的情况,即使是最有经验的开发人员也会感到困惑。

在本文中,我们将了解各种意想不到的 JavaScript 时刻,它们可能会让你感到困惑、考验你的极限,甚至让你感到沮丧。它也能帮助你改变你的编码方式。

你准备好让你的大脑爆炸了吗🤯?如果准备好了,那就让我们进入丛林吧。


1️⃣

2 == [2] // true
Enter fullscreen mode Exit fullscreen mode

==JS 中的运算符执行类型强制,这意味着它在进行比较之前尝试将要比较的值转换为常见数据类型。

在这个例子中,数字 2 被转换为字符串,数组[2]也被转换为字符串。结果两个值都是2。因此,比较结果为true

通常建议使用严格相等运算符===而不是,以==避免由于类型强制而导致意外结果。

探索更多:

'123' == 123        // true 
'foo' == NaN        // false
undefined == null   // true 
NaN === NaN         // false
NaN == NaN          // false
0 == null           // false
Enter fullscreen mode Exit fullscreen mode

2️⃣

[] == ![] // true
Enter fullscreen mode Exit fullscreen mode

将一个空数组[]一个非空数组(使用运算符boolean)求反后得到的值进行比较。比较的结果是,乍一看可能有点出乎意料。![]true

在 JS 中,每个值在上下文中都可以是true。空数组是真值,这意味着它被视为处于上下文中。当我们对它应用运算符时,它会被转换为falsebooleantrueboolean!false

另一方面,对boolean非空数组求反后得到的值为。当我们使用运算符false比较空数组(真值)和值(假值)时,JS 会执行类型约束,这意味着它会在比较之前尝试将值转换为通用类型。因此,空数组会被转换为 ,导致两边均为。最后,比较结果返回false==falsefalsetrue

探索更多:

['a', 'b'] !== ['a', 'b']   // true
['a', 'b'] == ['a', 'b']    // false
[1, 2] + [3, 4]             // "1,23,4" 
Enter fullscreen mode Exit fullscreen mode

3️⃣

null == undefined // true
Enter fullscreen mode Exit fullscreen mode

双等号==运算符用于比较两个值是否相等,同时忽略它们的数据类型。当使用双等号运算符比较两个值时,null它们undefined被视为相等,比较结果为true。这是因为 和 都null表示undefined缺少值,并且在这种情况下彼此等价。

使用严格相等运算符:

null === undefined // false
Enter fullscreen mode Exit fullscreen mode

4️⃣

typeof NaN   // number
typeof null  // object
Enter fullscreen mode Exit fullscreen mode

在 JS 中,typeof是一个用于确定值或变量类型的运算符。

NaN代表非数字,是 JS 中表示数字的特殊undefinedunrepresentable

当你使用typeofwith时NaN,它将返回number。这可能看起来很奇怪,但这是因为NaN从技术上讲,它在 JS 中是一种数字数据类型,即使它表示的实际上不是数字。

typeof应用于时null,它返回字符串object。这是因为null被视为一个表示空对象引用的特殊值。null本身不是对象,而是原始值。这被认为是 JS 语言设计中的一个怪癖或怪异之处。

探索更多:

typeof function(){}     // "function"
null instanceof Object  // false
Enter fullscreen mode Exit fullscreen mode

5️⃣

true == "1"  // true
false == "0" // true
Enter fullscreen mode Exit fullscreen mode

JS 将 字符串 转换1booleantrue,并将 字符串0转换为 ,false因为任何非空字符串都被视为真值,反之则为假值。因此,比较变成了true == true哪个是truefalse == false哪个是true

探索更多:

1 + true      // 2
1 - true      // 0
'' == false   // true
0 == false    // true
true + false  // 1
Enter fullscreen mode Exit fullscreen mode

6️⃣

"1" + 1    // "11"
2 + "2"    // "22"
"5" - 3    // 2
Enter fullscreen mode Exit fullscreen mode

当将+ 运算符与 astring和 a一起使用时number,数字将转换为字符串并与该字符串连接。

如果string可以解析为number,它将减去numberstring

所以,
"1" + 1变成字符串"11"
2 + "2"变成字符串"22"
"5" - 3变成数字2

探索更多:

+"1"                  // 1
-"1"                  // -1

+true                 // 1
-true                 // -1

+false                // 0
-false                // -0

+null                 // 0
+undefined            // NaN

1 / "2"               // 0.5
"2" / 1               // 2

1 / 0                 // Infinity
-1 / 0                // -Infinity

3 * "abc"             // NaN

true > false          // true  

undefined + 1         // NaN
undefined - 1         // NaN
undefined - undefined // NaN
undefined + undefined // NaN

null + 1              // 1
null - 1              // -1
null - null           // 0
null + null           // 0

Infinity + 1          // Infinity
Infinity - 1          // Infinity
Infinity - Infinity   // NaN
Infinity + Infinity   // Infinity
Infinity / Infinity   // NaN
Enter fullscreen mode Exit fullscreen mode

7️⃣

"b" + "a" + + "a" + "a" // "baNaNa"
Enter fullscreen mode Exit fullscreen mode

它将字符串b、字符串a、表达式产生的字符串+"a"和字符串连接起来a

+"a"强制将字符串a转换为数字,因为不是有效数字,所以计算结果为NaN(非数字) 。a

当我们连接baNaN(表示为空字符串)和 时a,我们得到字符串baNaNa


8️⃣

!{}       // false
{} == !{} // false
{} == {}  // false
Enter fullscreen mode Exit fullscreen mode

当我们将一个空对象{}与一个取反的空对象进行比较时!{}。感叹号!是一个逻辑运算符,它对对象的值进行取反,因此!{}返回结果false,因为在 JS 中对象被视为真值。我们实际上是{}在比较false哪个结果为false真,因为它们的值或数据类型不相等。

在最后一个表达式中,我们比较了两个空对象{}。尽管它们看起来相同,但它们是两个独立的对象,在内存中具有不同的引用,因此它们的值或数据类型并不相等。最终,比较结果也会有一个false值。

当在两个用花括号括起来的对象之间使用加号运算符 +{}时,它会尝试将对象连接为字符串。

探索更多:

{} + [] === ""  // false
!!{}            // true 
!![]            // true 
[] + []         // ""
[] + {}         // "[object Object]"
{} + []         // "[object Object]"
{} + {}         // "[object Object][object Object]"
[] == false     // true
!!''            // false
!!0             // false
!!null          // false
!!undefined     // false 
Enter fullscreen mode Exit fullscreen mode

9️⃣

7 > 6 > 5 // false
Enter fullscreen mode Exit fullscreen mode

首先,由于 7 大于 6,因此7 > 6求值为 。 接下来,求值为 。在 JS 中,被强制代入数字被强制代入。因此,因为不大于true
true > 5true1false01 > 5false15

所以最后,7 > 6 > 5相当于true > 5false

探索更多:

5 < 6 < 7  // true
0 > null   // false
Enter fullscreen mode Exit fullscreen mode

1️⃣0️⃣

Math.max() // -Infinity
Math.min() // Infinity
Enter fullscreen mode Exit fullscreen mode

Math.max()&Math.min()是分别可用于查找一组数字中的最大值和最小值的函数。

当不带任何参数调用时,Math.max()返回-Infinity代表 JS 中最小可能值的值number,另一方面,Math.min()返回代表JS 中Infinity最大可能值的值。number

这种行为是有道理的,因为如果没有提供数字,就没有最大的数字可以返回Math.max(),同样,也没有最小的数字可以返回Math.min()


1️⃣1️⃣

parseInt('08')       // 8
parseInt('08', 10)   // 8 
parseInt('0x10')     // 16 
Enter fullscreen mode Exit fullscreen mode

parseInt('08')将字符串转换08为整数8。如果您这样写parseInt('08', 10),函数仍然会返回8

其背后的原因是,parseInt函数的第二个参数是基数,它指定了要使用的计数系统。例如:binary、、等等。如果未指定基数,则会尝试根据字符串格式检测基数。在上述情况下,由于以 开头,因此被视为八进制数,octal因此它会被转换为十进制数。decimalhexadecimalparseInt0808

parseInt('0x10')hexadecimal将字符串转换0x10为整数16。基数也没有指定,但前缀0x表示该数字应被视为数字,hexadecimal因此它会被转换16为十进制数。

探索更多:

parseFloat('3.14.15')  // 3.14 
parseFloat('0.0')      // 0 
Enter fullscreen mode Exit fullscreen mode

1️⃣2️⃣

(function(x) { delete x; return x; })(1);   // 1
Enter fullscreen mode Exit fullscreen mode

一个接受参数 的匿名函数x。在函数内部,它会尝试删除x变量 ,但这是不可能的,因为x是函数参数,无法删除。然后,该函数返回 的值x

当使用参数 调用此函数时,函数内部1的值将被设置为。在这种情况下,删除操作不起作用,函数仅返回 的值,x1x1


1️⃣3️⃣来自 DEV 社区的
@tohodo为这篇文章补充了一个很棒的观点。我们来看看吧……

for (var i = 0; i < 3; ++i) {
  setTimeout(() => console.log(i), 1000); // returns 3 three times
}

for (let i = 0; i < 3; ++i) {
  setTimeout(() => console.log(i), 1000); // returns 0 1 2
}
Enter fullscreen mode Exit fullscreen mode

这是因为var在函数作用域中创建了单个绑定,所以在一秒超时后,循环已经运行完毕,因此你得到了3三次。通过使用let,你将变量绑定到块作用域(循环),因此它返回你期望的值,因为它i指的是该循环迭代时的值。

感谢@tohodo分享这一见解。


探索和理解这些 JavaScript 概念,你做得真棒!这些知识绝对能帮你应对面试,并让你作为面试官能够评估潜在候选人的技能。继续努力,继续学习!Ctrl+N


❤ 动机:

动机


🍀支持

请考虑关注并支持我们,订阅我们的频道。非常感谢您的支持,这将帮助我们继续创作您喜爱的内容。提前感谢您的支持!

YouTube
Discord
GitHub

杜尔·达塞尔 #8740

文章来源:https://dev.to/codeofrelevancy/unexpected-moments-of-javascript-that-will-challenge-your-understanding-of-the-language-4834
PREV
React 中的严格模式是什么?
NEXT
8 Ways to Be More Professional 1. Be Reachable 2. Be On Time 3. Listen Actively 4. Master Your Calendar 5. Speak Well, Write Well 6. Curate Your Brand 7. Read More Books 8. Consider Your Look You're Still You!