网站做一样没有侵权吧上海网站建设 百家号
2026/1/15 21:24:47 网站建设 项目流程
网站做一样没有侵权吧,上海网站建设 百家号,dede增加手机网站,软文推广代理平台玩转 JavaScript 的 rest 参数#xff1a;从入门到实战#xff0c;彻底告别 arguments你有没有写过这样的函数——传入的参数个数不固定#xff0c;有时候两个#xff0c;有时候五六个#xff1f;以前我们只能靠arguments对象来“猜”到底传了几个参数。但这个“老古董”既…玩转 JavaScript 的 rest 参数从入门到实战彻底告别 arguments你有没有写过这样的函数——传入的参数个数不固定有时候两个有时候五六个以前我们只能靠arguments对象来“猜”到底传了几个参数。但这个“老古董”既不是真正的数组又不能在箭头函数里用还让 TypeScript 报错连连。直到 ES6 带来了rest 参数...args一切都变了。它不只是语法糖而是一种思维方式的升级把不确定变成可控把隐式变成显式。今天我们就来手把手拆解 rest 参数的每一个细节让你从此不再为“参数太多怎么办”而头疼。为什么你需要放弃arguments先看一段“经典”的旧代码function sumAll() { let total 0; for (let i 0; i arguments.length; i) { total arguments[i]; } return total; }看起来没问题其实暗藏多个坑arguments不是数组不能直接调用.map()、.reduce()想要用数组方法得写成Array.prototype.slice.call(arguments)啰嗦又难懂在箭头函数中压根拿不到arguments—— 直接报错写 TypeScript类型系统完全不知道arguments到底是什么结构。而这些问题rest 参数一出手就全部解决。rest 参数到底是什么简单说rest 参数就是用来“收尾”的。当你定义一个函数时前面几个参数是明确的后面的“剩下的”全交给它打包成数组。语法也很直观function func(a, b, ...rest) { // a: 第一个参数 // b: 第二个参数 // rest: 剩下的所有参数组成的数组 }关键规则必须记住规则说明只能有一个一个函数最多只能有一个 rest 参数必须在最后它必须出现在参数列表的末尾否则会报SyntaxError永远是个数组即使没传多余参数rest也是[]而不是undefined不影响 length函数的.length属性只算命名参数不算 rest举个反例你就明白了// ❌ 错rest 不能放在中间 function bad(...rest, last) {} // ✅ 对rest 必须在最后 function good(first, second, ...rest) {}再来看看.length的表现function example(a, b, ...rest) {} console.log(example.length); // 输出 2 —— 只算 a 和 b这在做函数元编程或装饰器时特别有用你知道这个函数真正“期待”的参数有几个。为什么说 rest 参数是“真·数组”这是它和arguments最本质的区别。来看对比// 使用 arguments类数组 function oldSum() { // 必须转换才能用 reduce const args Array.prototype.slice.call(arguments); return args.reduce((sum, n) sum n, 0); } // 使用 rest 参数真数组 function newSum(...numbers) { return numbers.reduce((sum, n) sum n, 0); }看到区别了吗一个是“我要想办法把它变数组”另一个是“它本来就是”。你可以放心大胆地使用所有数组方法function filterPositive(...values) { return values.filter(x x 0); } function logEach(...msgs) { msgs.forEach(msg console.log([LOG], msg)); }再也不用手动遍历arguments了。实战场景这些地方你一定要用 rest 参数场景一封装灵活的日志函数你想做一个带前缀的日志工具比如[INFO]或[ERROR]后面还能跟任意数量的消息。function log(level, ...messages) { const time new Date().toISOString().split(T)[1].slice(0, -5); console.log([${time}] [${level}], ...messages); } log(WARN, User not found, retry2, { userId: 123 }); // 输出: [10:30:45] [WARN] User not found retry2 { userId: 123 }注意这里用了两个技巧-...messages收集所有消息-console.log(...messages)用展开运算符原样输出保持原始格式。场景二构建高阶函数工厂想创建一个可以“预设配置”的函数rest 参数 闭包 是绝配。function createSender(serviceName, ...tags) { return (...events) { events.forEach(event { console.log([${serviceName}], ...tags, event:, event); }); }; } const apiLogger createSender(API, v1, auth); apiLogger(login_start, token_expired); // 输出: [API] v1 auth event: login_start // [API] v1 auth event: token_expired这种模式在中间件、埋点系统、插件机制中非常常见。场景三兼容多种调用方式的 API 设计很多库都支持“灵活传参”。比如你可以传多个字符串也可以传一个对象数组。function trackEvent(category, action, ...payload) { const metadata { category, action, timestamp: Date.now(), details: payload.length 1 ? payload[0] : payload }; // 模拟上报 console.log(Track:, metadata); } // 多种调用方式都支持 trackEvent(ui, click, button-A); trackEvent(user, login, { method: email }, from_mobile);通过判断payload的长度和类型我们可以智能处理不同入参风格对外提供更友好的接口。场景四性能监控包装器函数代理想给某个函数加上计时功能不用改原逻辑用 rest 参数轻松实现function withTiming(fn, label) { return (...args) { console.time(label); const result fn(...args); // 展开传递 console.timeEnd(label); return result; }; } // 使用示例 const add (a, b) a b; const timedAdd withTiming(add, 加法耗时); timedAdd(5, 7); // 控制台输出加法耗时: 0.1ms这就是典型的 AOP面向切面编程思想rest 参数在这里起到了“参数搬运工”的关键作用。结合解构更强的参数设计模式rest 参数不仅能自己用还能和解构赋值搭配写出更专业的函数签名。function processUser({ name, age }, ...preferences) { console.log(${name}(${age}) likes:, preferences.join(, )); } processUser({ name: Alice, age: 24 }, music, hiking, coffee); // 输出: Alice(24) likes: music, hiking, coffee这样做的好处是- 第一个参数明确要求是一个用户对象- 后续的兴趣爱好作为可变参数传入- 调用者一眼就能看出哪些是必填项哪些是可选项。TypeScript 中的最佳实践如果你用 TypeScriptrest 参数简直是类型系统的“好朋友”。function pushToT(target: T[], ...items: T[]): void { target.push(...items); } const list: number[] [1, 2]; pushTo(list, 3, 4, 5); // 类型安全 ✔️泛型 rest 参数保证了items的每个元素都和target是同一类型编译器全程帮你检查。还可以配合 JSDoc 提升可读性/** * 发送通知支持多个附加字段 * param {string} type - 通知类型 * param {string} title - 标题 * param {...*} fields - 其他附加信息 */ function notify(type, title, ...fields) { console.log([${type}] ${title}, fields); }IDE 能自动识别...fields的含义团队协作更顺畅。常见误区与避坑指南❌ 误用把所有函数都改成 rest别走极端不是每个函数都需要...args。// ❌ 过度设计 function greet(...names) { names.forEach(name console.log(Hello ${name})); } // ✅ 更合理 function greet(name) { console.log(Hello ${name}); }只有当“参数数量不确定”确实是业务需求时才使用 rest 参数。⚠️ 性能提醒大数据量要小心虽然语法上没问题但如果传入上千个参数...rest会生成一个大数组可能影响内存和 GC。一般情况下无需担心但在高频调用或底层库中要注意// 高频场景慎用 function collectMetrics(...values) { // 如果每秒调用几千次且每次传几百个值… metricsBuffer.push(...values); }建议在这种场景下考虑流式处理或分批提交。 箭头函数中的王者地位这一点必须强调箭头函数没有自己的argumentsconst bad () { console.log(arguments); // ReferenceError! }; const good (...args) { console.log(Received:, args); // ✅ 完美工作 };所以在箭头函数中处理多参数rest 参数是唯一选择。总结你该怎样正确使用 rest 参数使用建议说明✅ 明确区分必需与可选参数前面写死后面用...rest收尾✅ 给 rest 参数起好名字用options、callbacks、tags等语义化名称✅ 配合 spread 运算符转发参数fn(...args)是标准范式✅ 在 TypeScript 中使用泛型约束类型提升类型安全性✅ 文档中标注用途用 JSDoc 让别人看得懂 不要滥用并非所有函数都需要变参写在最后...rest看似只是一个小小的三个点但它背后代表的是 JavaScript 向声明式、函数式、工程化演进的重要一步。它让我们告别了arguments的晦涩与局限拥有了更清晰、更安全、更现代的参数处理能力。无论是写工具函数、封装 SDK、构建中间件还是开发 React Hook你会发现 rest 参数无处不在。所以下次当你又要写function(...)的时候不妨问一句自己“我是不是该用...rest来让它更优雅一点”如果你正在学习现代 JavaScript或者想提升代码质量那么掌握 rest 参数绝对是最值得的投资之一。互动时间你在项目中用过哪些巧妙的 rest 参数用法欢迎在评论区分享你的实战经验

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询