本文来分享一些前端 JavaScript 中离谱的设计,这些设计日常开发遇到的概率可能比较小,而且一旦在开发中遇到了,大概率只能自认倒霉了。
所以建议朋友们认真阅读本篇文章,应该能涨不少知识~
学前端的朋友们,看看以下设计你了解过几个呢?
parseInt(0.0000005)
答案:5
parseInt(0.5); // -> 0
parseInt(0.05); // -> 0
parseInt(0.005); // -> 0
parseInt(0.0005); // -> 0
parseInt(0.00005); // -> 0
parseInt(0.000005); // -> 0
parseInt(0.0000005); // -> 5
parseInt
函数将其第一个参数转换为字符串(如果它还不是字符串),然后再转换为数字。当将 0.0000005 转换为字符串时,会得到以下结果:
String(0.0000005); // -> "5e-7"
然后 parseInt
函数只取该字符串的第一个字符,即 5,并将其解析为一个数字。
[] == ![]
答案:true
[] == ![]
之所以返回 true
,是因为比较过程中发生了隐式的类型转换。下面来逐步解析:
-
[]
是一个空数组,它是真值。![]
是false
,因为当将空数组强制转换为布尔值时,它变为true
,然后被否定为false
。因此,比较变成了[] == false
。 -
当比较不同类型时,JavaScript 将尝试将一个或两个值强制转换为相同类型。在这种情况下,它将尝试将数组强制转换为原始值。
-
一个空数组,当被强制转换为原始值时,变成了一个空字符串
""
。因此,表达式[] == false
实际上变成了"" == false
。 -
现在,JavaScript 尝试将布尔值
false
转换为数字,即0
,表达式就变成了"" == 0
。 -
根据 JavaScript 的规则,当比较一个字符串和一个数字时,字符串将被强制转换为数字。因此,
""
被强制转换为数字后变成了0
。这时比较的就是0 == 0
,结果是true
。
NaN === NaN
答案:false
在 JavaScript 中,NaN(Not a Number)是一个特殊的值,表示一个非数字的值。然而,当使用 ===(严格相等运算符)来比较 NaN 时,会出现一个特殊的情况:NaN 并不等于 NaN。具体来说,NaN === NaN 的结果是 false,尽管两者都是 NaN。这是因为在 IEEE 754 浮点数标准中,NaN 被定义为不等于任何其他值,包括它自身。
要检查一个值是否是 NaN,通常使用 isNaN() 函数,但请注意,isNaN() 对于非数字类型的参数(如字符串或对象)也可能返回 true,因为它会尝试将这些参数转换为数字。更严格的检查方法是使用 Number.isNaN(),它只有在参数确实是 NaN 时才返回 true。
NaN === NaN // false
isNaN(NaN); // true,但这不是最佳方式
Number.isNaN(NaN); // true,这是更好的方式
[1, 2] + [3, 4]
答案:"1,23,4"
在 JavaScript 中,当尝试使用 + 运算符来连接两个数组,实际上并不会执行数组的拼接或合并。相反,由于 +
运算符在 JavaScript 中既可以用作加法运算符(对于数字),也可以用作字符串连接运算符(对于字符串),因此数组会首先被转换为字符串,然后再进行连接。
数组到字符串的转换是通过调用数组的 toString()
方法实现的,这通常会生成一个由数组元素组成的逗号分隔的字符串。因此,[1, 2]
会被转换为 "1,2"
,而 [3, 4]
会被转换为 "3,4"
。然后,这两个字符串会被 +
运算符连接起来,得到 "1,23,4"
。所以,[1, 2] + [3, 4]
的结果是 "1,23,4"
。
如果想要合并两个数组,应该使用数组的 concat()
方法或扩展运算符如下所示:
-
使用 concat() 方法:
const result = [1, 2].concat([3, 4]); // [1, 2, 3, 4]
-
使用扩展运算符:
const result = [...[1, 2], ...[3, 4]]; // [1, 2, 3, 4]
typeof null
答案:object
。
在 JavaScript 早期版本中,所有值都存储在 32 位的单元中,每个单元包含一个小的 类型标签(1-3 bits) 以及当前要存储的数据。类型标签共有五种类型:
000: object - 数据类型为 对象。
1: int - 数据类型为 有符号整数。
010: double - 数据类型为 双精度的浮点数。
100: string - 数据类型为 字符串。110: boolean - 数据类型为 布尔值。
null
的值是机器码 NULL
指针(指针值是000
),也就是说null
的类型标签也是 000
,和object
的类型标签一样,所以会被判定为object
。
try...finally
答案:2
(() => {
try {
return 1;
} finally {
return 2;
}
})();
在JavaScript中,当在一个函数(包括箭头函数)的try
块和finally
块中都有return
语句时,finally
块中的return
语句会覆盖try
块中的return
语句。这是因为finally
块总是会被执行,无论try
块中的代码是否成功执行,或者是否抛出了异常。而且,如果finally
块中有return
语句,那么这个return
语句将决定整个函数的返回值。
0.14 * 100
答案:14.000000000000002
0.13 * 100 // 13
0.14 * 100 // 14.000000000000002
0.15 * 100 // 15
0.16 * 100 // 16
在JavaScript中,所有的数字都是以 64 位浮点数形式存储的,即使它们被声明为整数。由于二进制无法精确表示所有的十进制小数,因此在进行浮点数运算时,可能会出现精度问题。由于在二进制浮点数表示中,0.14 不能精确表示,因此在进行乘法运算时会出现微小的舍入误差。一个经典的问题就是 0.1 + 0.2 不等于 0.3。这两个问题出现的原因是一样的。
0.1 + 0.2 === 0.3 // false
0.1 + 0.5 === 0.6 // true
为了处理这种精度问题,可以使用Number.EPSILON
和Math.round
、toFixed
等方法来比较浮点数或将其格式化为固定小数位数。如果需要精确计算,并且不能容忍这种舍入误差,可以使用特殊的库,如decimal.js
或bignumber.js
,它们提供了高精度的十进制数运算。
1.toString()
答案:报错
const num = 1;
num.toString() // 1
1.toString(); // Uncaught SyntaxError: Invalid or unexpected token
1..toString(); // 1
在 JavaScript 中,1.toString()
会导致一个语法错误,因为点号(.
)在这里被解析为浮点数的一部分,但紧接着并没有另一个数字来形成有效的浮点数字面量,所以解析器会抛出一个 Uncaught SyntaxError: Invalid or unexpected token
错误。
然而,当写 1..toString()
时,情况就不同了。这里有两个点号,但第一个点号实际上并不是浮点数的一部分。这是因为 JavaScript 的解析器在遇到连续的点号时会将它们视为一种特殊的语法结构,即第一个点号被视为数字 1 的结尾(尽管在这里它并没有实际意义,因为 1 已经是完整的数字),而第二个点号则作为访问对象属性的操作符。
因此,1..toString()
实际上是这样被解析的:
-
数字 1 被解析为一个完整的数字字面量。
-
由于紧接着有一个点号,但它并没有跟随另一个数字来形成浮点数,所以它被解释为对象属性的访问操作符。
-
因为 1 在 JavaScript 中是一个原始值,它本身并没有
.toString()
方法,但是在这里,由于点号操作符的存在,JavaScript 会尝试将 1 转换为一个Number
对象(这是一个称为装箱或自动封装的过程)。 -
一旦 1 被转换为
Number
对象,就可以调用它的.toString()
方法了。
所以,1..toString()
最终会返回字符串 "1",尽管这种写法在实际编程中并不常见,因为它可能会引起混淆。更常见的做法是直接对数字变量使用 .toString()
方法,也就是上面的第一种写法。
Math.max() < Math.min()
答案:true
Math.max() < Math.min() // true
Math.max() // -Infinity
Math.min() // Infinity
在标准的 JavaScript 环境中,Math.max()
在没有参数时应该返回 -Infinity
,而 Math.min()
在没有参数时应该返回 Infinity
。但是,由于 Infinity
总是大于 -Infinity
,所以 Math.max() < Math.min()
返回 true。
9007199254740992 === 9007199254740993
答案:true
JavaScript 的 Number 类型是基于 IEEE 754 标准 (也称为 64 位浮点数)实现的,这意味着它有一些限制,特别是关于可以精确表示的数字的范围和精度。在 IEEE 754 标准中,最大的安全整数(即可以精确表示的最大整数)是 Number.MAX_SAFE_INTEGER
,其值为 9007199254740991
(2 的 53 次方减 1)。
当尝试使用大于 Number.MAX_SAFE_INTEGER
的整数时,JavaScript 会尝试将其存储为一个近似的浮点数,这可能会导致精度损失。在这个例子中,9007199254740992
和 9007199254740993
都会被转换为近似的浮点数,但由于精度限制,这两个数字可能会表示为相同的浮点数值。
因此,如果需要在 JavaScript 中表示大数字时,建议使用字符串来存储大数,以避免精度丢失。
来自-前端充电宝,欢迎大家关注!
在线备战面试、刷题指南,拿走不谢,要学会站在别人的肩膀上提升自己点击这里-->
最后:
如果你现在正在找工作,可以私信“web”或者直接添加下方小助理进群领取前端面试小册、简历优化修改、大厂内推以及更多阿里、字节大厂面试真题合集,和p8大佬一起交流。
标签:JavaScript,数字,前端,巨坑,NaN,toString,字符串,自认倒霉,浮点数 From: https://blog.csdn.net/Likestarr/article/details/139523119