• JavaScript中你可以拿来和同事“炫技”的知识点
  • 发布于 2个月前
  • 309 热度
    0 评论
JavaScript 作为一门动态的脚本语言,有着无穷的灵活性和意想不到的特性。即使你已经是一名资深开发者,也可能会对某些冷知识感到意外。本文整理了一些 JavaScript 冷知识,既有实用性,也有趣味性,希望你看完之后可以在项目中实践或者用来和同事“炫技”。

1. [] == ![] 的结果为什么是 true?
console.log([] == ![]); // true
解析:
这个问题乍看起来毫无道理,但实际上是 JavaScript 的类型转换规则导致的。
「![] 转换为布尔值」:
空数组是一个对象,它的布尔值为 true,但 ![] 是 false。
「类型转换规则」:
== 会将两边的操作数转换为相同类型。
[] 转为字符串,变成 ""。
![] 是 false,转换为数字为 0。
「最终比较」:
"" == 0 为 true,因为空字符串会被转为数字 0。

2. 0.1 + 0.2 === 0.3 为什么是 false?
console.log(0.1 + 0.2 === 0.3); // false
解析:
这是由于 JavaScript 使用 IEEE 754 双精度浮点数表示数字。这种表示方式无法精确存储某些十进制小数,导致计算时产生了微小的误差。
// 堆代码 duidaima.com
console.log(0.1 + 0.2); // 0.30000000000000004
解决方案:
通过 Number.EPSILON 校正误差:
console.log(Math.abs(0.1 + 0.2 - 0.3) < Number.EPSILON); // true
3. Object.is() 和 === 的微妙区别
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() 是更可靠的选择。

4. 小数点后直接调用方法
你知道可以直接对数字调用方法吗?不过写法需要小心。
console.log(5..toString());   // "5"
console.log(5 .toString());  // "5"
console.log((5).toString()); // "5"
解析:
第一个点是小数点,第二个点是对象访问符。为了避免歧义,括号或者额外的空格可以让代码更清晰。

5. JavaScript 的 + 是个多面手
+ 在 JavaScript 中不仅仅是一个加法运算符,它还能用于类型转换:
console.log(+"123");    // 123 (字符串变为数字)
console.log(+true);     // 1
console.log(+false);    // 0
console.log(+null);     // 0
console.log(+undefined);// NaN
实用场景:
快速将字符串转为数字,替代 parseInt 或 Number()。

6. 函数参数的“魔术”变化
JavaScript 的函数参数对象 arguments 并不是一个真正的数组,它是一个“类数组对象”。不过,在严格模式下,它的行为发生了变化。
function test(a, b) {
  a = 10;
  console.log(arguments[0]); // 非严格模式:10;严格模式:1
}
test(1, 2);
解析:
在非严格模式下,修改参数变量会同步更新 arguments 对象。
在严格模式下,参数和 arguments 之间不再同步。

7. 函数默认参数也有作用域
函数的默认参数值可以访问之前的参数:
function greet(name, message = `Hello, ${name}`) {
  return message;
}
console.log(greet("Alice")); // Hello, Alice
解析:
默认参数在定义时会创建作用域链,后面的参数可以引用前面的参数。

8. “冻结”的对象仍可修改内部属性
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; // 不会修改
9. setTimeout 的最短延迟时间是 4ms
即使你设置了 setTimeout 的延迟为 0ms,浏览器仍然会将其最短延迟设置为 4ms。
setTimeout(() => console.log("Hello"), 0);
console.log("World");
// 输出顺序:World -> Hello
解析:
JavaScript 的事件循环机制规定,setTimeout 的回调最早在下一次事件循环执行,而非立即执行。

10. 使用正则表达式判断素数
虽然看起来不可思议,但你可以用正则表达式判断一个数字是否是素数。
function isPrime(number) {
  return !/^1?$|^(11+?)\1+$/.test("1".repeat(number));
}
console.log(isPrime(7)); // true
console.log(isPrime(8)); // false
解析:
正则匹配通过重复检测数字是否可以被整除,若不能整除则为素数。

结语
JavaScript 是一门让人又爱又恨的语言。它的灵活性既给我们带来了便利,也让它充满了奇怪的冷知识。希望这些冷知识能让你在开发中找到新的乐趣!如果你也有发现其他有趣的知识点,欢迎在评论区补充!
用户评论