JavaScript 中意想不到的时刻将挑战你对该语言的理解
JavaScript是世界上最流行的编程语言之一,被广泛用于构建动态交互式网站、Web 应用程序,甚至桌面和移动应用程序。JavaScript 因其广泛的应用和与各种平台的兼容性,成为了通往其他 Web 技术的门户。它已成为现代 Web 开发的基础语言。但它同时也是一种复杂的语言,其中存在许多意想不到的情况,即使是最有经验的开发人员也会感到困惑。
在本文中,我们将了解各种意想不到的 JavaScript 时刻,它们可能会让你感到困惑、考验你的极限,甚至让你感到沮丧。它也能帮助你改变你的编码方式。
你准备好让你的大脑爆炸了吗🤯?如果准备好了,那就让我们进入丛林吧。
1️⃣
2 == [2] // true
==JS 中的运算符执行类型强制,这意味着它在进行比较之前尝试将要比较的值转换为常见数据类型。
在这个例子中,数字 2 被转换为字符串,数组[2]也被转换为字符串。结果两个值都是2。因此,比较结果为true。
通常建议使用严格相等运算符===而不是,以==避免由于类型强制而导致意外结果。
探索更多:
'123' == 123 // true
'foo' == NaN // false
undefined == null // true
NaN === NaN // false
NaN == NaN // false
0 == null // false
2️⃣
[] == ![] // true
将一个空数组[]与一个非空数组(使用运算符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"
3️⃣
null == undefined // true
双等号==运算符用于比较两个值是否相等,同时忽略它们的数据类型。当使用双等号运算符比较两个值时,null它们undefined被视为相等,比较结果为true。这是因为 和 都null表示undefined缺少值,并且在这种情况下彼此等价。
使用严格相等运算符:
null === undefined // false
4️⃣
typeof NaN // number
typeof null // object
在 JS 中,typeof是一个用于确定值或变量类型的运算符。
NaN代表非数字,是 JS 中表示数字的特殊undefined值unrepresentable。
当你使用typeofwith时NaN,它将返回number。这可能看起来很奇怪,但这是因为NaN从技术上讲,它在 JS 中是一种数字数据类型,即使它表示的实际上不是数字。
当typeof应用于时null,它返回字符串object。这是因为null被视为一个表示空对象引用的特殊值。null本身不是对象,而是原始值。这被认为是 JS 语言设计中的一个怪癖或怪异之处。
探索更多:
typeof function(){} // "function"
null instanceof Object // false
5️⃣
true == "1" // true
false == "0" // true
JS 将 字符串 转换1为boolean值true,并将 字符串0转换为 ,false因为任何非空字符串都被视为真值,反之则为假值。因此,比较变成了true == true哪个是true和false == false哪个是true。
探索更多:
1 + true // 2
1 - true // 0
'' == false // true
0 == false // true
true + false // 1
6️⃣
"1" + 1 // "11"
2 + "2" // "22"
"5" - 3 // 2
当将+ 运算符与 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
7️⃣
"b" + "a" + + "a" + "a" // "baNaNa"
它将字符串b、字符串a、表达式产生的字符串+"a"和字符串连接起来a。
+"a"强制将字符串a转换为数字,因为不是有效数字,所以计算结果为NaN(非数字) 。a
当我们连接b、a、NaN(表示为空字符串)和 时a,我们得到字符串baNaNa。
8️⃣
!{} // false
{} == !{} // false
{} == {} // false
当我们将一个空对象{}与一个取反的空对象进行比较时!{}。感叹号!是一个逻辑运算符,它对对象的值进行取反,因此!{}返回结果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
9️⃣
7 > 6 > 5 // false
首先,由于 7 大于 6,因此7 > 6求值为 。 接下来,求值为 。在 JS 中,被强制代入数字,被强制代入。因此为,因为不大于。truetrue > 5true1false01 > 5false15
所以最后,7 > 6 > 5相当于true > 5。false
探索更多:
5 < 6 < 7 // true
0 > null // false
1️⃣0️⃣
Math.max() // -Infinity
Math.min() // Infinity
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
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
1️⃣2️⃣
(function(x) { delete x; return x; })(1); // 1
一个接受参数 的匿名函数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
}
这是因为var在函数作用域中创建了单个绑定,所以在一秒超时后,循环已经运行完毕,因此你得到了3三次。通过使用let,你将变量绑定到块作用域(循环),因此它返回你期望的值,因为它i指的是该循环迭代时的值。
感谢@tohodo分享这一见解。
探索和理解这些 JavaScript 概念,你做得真棒!这些知识绝对能帮你应对面试,并让你作为面试官能够评估潜在候选人的技能。继续努力,继续学习!Ctrl+N
❤ 动机:
🍀支持
请考虑关注并支持我们,订阅我们的频道。非常感谢您的支持,这将帮助我们继续创作您喜爱的内容。提前感谢您的支持!
文章来源:https://dev.to/codeofrelevancy/unexpected-moments-of-javascript-that-will-challenge-your-understanding-of-the-language-4834
后端开发教程 - Java、Spring Boot 实战 - msg200.com

