网站首页 > 技术文章 正文
尽管我们对 JavaScript 已经相当熟悉了,但这门语言中仍存在许多有趣的特性和行为,今天分享 12 个鲜为人知的 JavaScript 冷知识。
1. 函数的长度属性
你可能知道数组有 length 属性,但函数也有!函数的 length 属性返回函数期望的参数个数(形参数量)。
function foo(a, b, c = 3) { return a + b + c; }
console.log(foo.length); // 2,不包括带默认值的参数!
function bar(a, b = 2, c) { return a + b + c; }
console.log(bar.length); // 1,从第一个带默认值的参数开始后面的都不算
(() => {}).length; // 0
((...args) => {}).length; // 0
这个特性在编写高阶函数或函数式编程时特别有用,可以用来进行函数的参数匹配。
2. void 运算符不只是不返回值
void 运算符不仅可以用来确保表达式不返回值,还可以用来解决一些特殊问题:
// 1. 防止箭头函数返回值
const onClick = () => void doSomething();
// 2. 创建纯净的 undefined
let undefined = 'hello';
console.log(void 0); // undefined
// 3. 立即执行 Promise
void Promise.resolve().then(() => {
console.log('异步执行');
});
// 4. 阻止默认的 href 跳转
<a href="javascript:void(0)">点击</a>
3. Function.prototype.toString() 的变化
ES2019 之后,
Function.prototype.toString() 会保留函数的原始格式,包括注释和空格:
function /* 这是注释 */ foo() {
console.log("Hello"); // 这也是注释
}
console.log(foo.toString());
// function /* 这是注释 */ foo() {
// console.log("Hello"); // 这也是注释
// }
// 甚至适用于内置函数
console.log(Array.prototype.push.toString());
// "function push() { [native code] }"
4. 逗号运算符的隐藏用途
逗号运算符可以在一些意想不到的地方使用,比如箭头函数或三元运算符中:
// 在箭头函数中执行多条语句
const increment = x => (console.log(x), x + 1);
// 在三元运算符中执行多个操作
const result = condition
? (func1(), func2(), value1)
: (func3(), func4(), value2);
// 在数组方法中巧妙运用
const arr = [1, 2, 3];
arr.map(x => (x *= 2, x -= 1)); // [1, 3, 5]
5. 可选链操作符的隐藏技巧
可选链操作符不仅可以用于对象属性,还可以用于函数调用和数组:
// 函数调用
const result = someFunction?.();
// 数组访问
const arr = null;
console.log(arr?.[0]); // undefined
// 动态属性名
const propName = null;
console.log(obj?.[propName?.toString()]); // undefined
// 与空值合并操作符组合
const value = obj?.prop ?? 'default';
6. Symbol.asyncIterator 的妙用
你可以使用 Symbol.asyncIterator 创建自定义的异步迭代器:
7. 利用 Object.defineProperty 创建常量对象
你可以创建真正的常量对象,其属性完全不可修改:
8. Label 语句的妙用
JavaScript 中的 label 语句虽然不常见,但在特定场景下非常有用,特别是在嵌套循环中:
9. 使用 Proxy 实现私有属性
在类私有字段还未普及之前,可以使用 Proxy 来模拟私有属性:
10. 利用 Generator 实现范围数据类型
JavaScript 没有原生的范围类型,但我们可以用 Generator 实现:
11. BigInt 的特殊行为
BigInt 有一些出人意料的行为:
12. Intl API 的强大功能
Intl API 不仅可以用于格式化日期和数字,还有很多强大的功能:
// 相对时间格式化
const rtf = new Intl.RelativeTimeFormat('zh', { numeric: 'auto' });
console.log(rtf.format(-1, 'day')); // "昨天"
console.log(rtf.format(7, 'day')); // "7天后"
// 复数规则
const pr = new Intl.PluralRules('en-US');
console.log(pr.select(0)); // "other"
console.log(pr.select(1)); // "one"
console.log(pr.select(2)); // "other"
// 分段器
const segmenter = new Intl.Segmenter('zh', { granularity: 'word' });
const segments = segmenter.segment('你好,世界!');
console.log([...segments].map(s => s.segment)); // ["你好", ",", "世界", "!"]
猜你喜欢
- 2025-07-23 ASP.NET MVC+Bootstrap个人博客之文章打赏(六)
- 2025-07-23 void 0 和 undefined 哪个更好?一个奇怪但有用的知识点
- 2025-07-23 网页文字无法复制,教你一招解决!
- 2025-04-26 佛国佛塔佛缘--缅甸(1)
- 2025-04-26 无聊了?玩玩这个任意摧毁破坏网页的小游戏吧!
- 2025-04-26 js函数常见的写法以及调用方法
- 2025-04-26 网页文本禁止复制粘贴?教你6个方法,轻松搞定!你学不学?
- 2025-04-26 涨停王者千机令博客的博客
- 2025-04-26 JavaScript 实现点击/关闭全屏
- 2025-04-26 镇安冷安路拓宽建设 沿途暂时实行交通管制
- 08-06中等生如何学好初二数学函数篇
- 08-06C#构造函数
- 08-06初中数学:一次函数学习要点和方法
- 08-06仓颉编程语言基础-数据类型—结构类型
- 08-06C++实现委托机制
- 08-06初中VS高中三角函数:从"固定镜头"到"360°全景",数学视野升级
- 08-06一文讲透PLC中Static和Temp变量的区别
- 08-06类三剑客:一招修改所有对象!类方法与静态方法的核心区别!
- 1524℃桌面软件开发新体验!用 Blazor Hybrid 打造简洁高效的视频处理工具
- 658℃Dify工具使用全场景:dify-sandbox沙盒的原理(源码篇·第2期)
- 528℃MySQL service启动脚本浅析(r12笔记第59天)
- 494℃启用MySQL查询缓存(mysql8.0查询缓存)
- 493℃服务器异常重启,导致mysql启动失败,问题解决过程记录
- 480℃「赵强老师」MySQL的闪回(赵强iso是哪个大学毕业的)
- 462℃mysql服务怎么启动和关闭?(mysql服务怎么启动和关闭)
- 461℃MySQL server PID file could not be found!失败
- 最近发表
- 标签列表
-
- cmd/c (90)
- c++中::是什么意思 (84)
- 标签用于 (71)
- 主键只能有一个吗 (77)
- c#console.writeline不显示 (95)
- pythoncase语句 (88)
- es6includes (74)
- sqlset (76)
- windowsscripthost (69)
- apt-getinstall-y (100)
- node_modules怎么生成 (87)
- chromepost (71)
- flexdirection (73)
- c++int转char (80)
- mysqlany_value (79)
- static函数和普通函数 (84)
- el-date-picker开始日期早于结束日期 (70)
- asynccallback (71)
- localstorage.removeitem (74)
- vector线程安全吗 (70)
- java (73)
- js数组插入 (83)
- mac安装java (72)
- 查看mysql是否启动 (70)
- 无效的列索引 (74)