hello大家好,我是Range。
JavaScript有很多奇怪的不容易理解的特性(bug?),想要写出比较健壮的JavaScript代码,又不能不去了解这些知识点。今天带来 一篇短文,介绍了一些常见的冷知识。
另外,推荐大家都去看看《Javascript: The Good Parts》这本书,薄薄的一本,也不会耽误刷小视频的时间
下面是正文部分。
JavaScript 作为一门动态的脚本语言,有着无穷的灵活性和意想不到的特性。即使你已经是一名资深开发者,也可能会对某些冷知识感到意外。本文整理了一些 JavaScript 冷知识,既有实用性,也有趣味性,希望你看完之后可以在项目中实践或者用来和同事“炫技”。
console.log([] == ![]); // true
这个问题乍看起来毫无道理,但实际上是 JavaScript 的类型转换规则导致的。
「![]
转换为布尔值」:
空数组是一个对象,它的布尔值为 true
,但 ![]
是 false
。
「类型转换规则」:
==
会将两边的操作数转换为相同类型。
[]
转为字符串,变成 ""
。
![]
是 false
,转换为数字为 0
。
「最终比较」:
"" == 0
为 true
,因为空字符串会被转为数字 0
。
console.log(0.1 + 0.2 === 0.3); // false
这是由于 JavaScript 使用 IEEE 754 双精度浮点数表示数字。这种表示方式无法精确存储某些十进制小数,导致计算时产生了微小的误差。
console.log(0.1 + 0.2); // 0.30000000000000004
通过 Number.EPSILON
校正误差:
console.log(Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON); // true
console.log(Object.is(NaN, NaN)); // true
console.log(NaN === NaN); // false
Object.is()
用来比较两个值是否完全相同,和 ===
很相似,但处理特殊值(如 NaN
和 -0
)时有区别:
「NaN
比较」:
===
:NaN
不等于自身。
Object.is()
:NaN
等于自身。
「-0
和 +0
」:
console.log(Object.is(-0, +0)); // false
console.log(-0 === +0); // true
当你需要精确比较特殊值时,Object.is()
是更可靠的选择。
你知道可以直接对数字调用方法吗?不过写法需要小心。
console.log(5..toString()); // "5"
console.log(5 .toString()); // "5"
console.log((5).toString()); // "5"
第一个点是小数点,第二个点是对象访问符。
为了避免歧义,括号或者额外的空格可以让代码更清晰。
+
在 JavaScript 中不仅仅是一个加法运算符,它还能用于类型转换:
console.log(+"123"); // 123 (字符串变为数字)
console.log(+true); // 1
console.log(+false); // 0
console.log(+null); // 0
console.log(+undefined);// NaN
快速将字符串转为数字,替代 parseInt
或 Number()
。
JavaScript 的函数参数对象 arguments
并不是一个真正的数组,它是一个“类数组对象”。不过,在严格模式下,它的行为发生了变化。
function test(a, b) {
a = 10;
console.log(arguments[0]); // 非严格模式:10;严格模式:1
}
test(1, 2);
在非严格模式下,修改参数变量会同步更新 arguments
对象。
在严格模式下,参数和 arguments
之间不再同步。
函数的默认参数值可以访问之前的参数:
function greet(name, message = `Hello, ${name}`) {
return message;
}
console.log(greet("Alice")); // Hello, Alice
默认参数在定义时会创建作用域链,后面的参数可以引用前面的参数。
Object.freeze()
冻结的是对象本身,而非其内部的属性。
const obj = { nested: { value: 1 } };
Object.freeze(obj);
obj.nested.value = 42;
console.log(obj.nested.value); // 42
如果需要真正冻结,可以递归处理:
function deepFreeze(obj) {
Object.freeze(obj);
Object.keys(obj).forEach((key) => {
if (typeof obj[key] === "object") {
deepFreeze(obj[key]);
}
});
}
const obj2 = { nested: { value: 1 } };
deepFreeze(obj2);
obj2.nested.value = 42; // 不会修改
即使你设置了 setTimeout
的延迟为 0ms
,浏览器仍然会将其最短延迟设置为 4ms
。
setTimeout(() => console.log("Hello"), 0);
console.log("World");
// 输出顺序:World -> Hello
JavaScript 的事件循环机制规定,setTimeout
的回调最早在下一次事件循环执行,而非立即执行。
虽然看起来不可思议,但你可以用正则表达式判断一个数字是否是素数。
function isPrime(number) {
return !/^1?$|^(11+?)\1+$/.test("1".repeat(number));
}
console.log(isPrime(7)); // true
console.log(isPrime(8)); // false
正则匹配通过重复检测数字是否可以被整除,若不能整除则为素数。
JavaScript 是一门让人又爱又恨的语言。它的灵活性既给我们带来了便利,也让它充满了奇怪的冷知识。希望这些冷知识能让你在开发中找到新的乐趣!如果你也有发现其他有趣的知识点,欢迎在评论区补充!
原文链接:https://juejin.cn/post/7451763317440790568
还没有使用过我们刷题网站(https://fe.ecool.fun/)或者刷题小程序的同学,如果近期准备或者正在找工作,千万不要错过,题库主打题全和更新快哦~。
有会员购买、辅导咨询的小伙伴,可以通过下面的二维码,联系我们的小助手。