南平市网站建设_网站建设公司_测试上线_seo优化
2026/1/14 12:02:45 网站建设 项目流程


扩展运算符 vs Rest 参数:前端新人别再傻傻分不清了!

  • 扩展运算符 vs Rest 参数:前端新人别再傻傻分不清了!
    • 先甩一句狠话:... 这三个点,就是前端界的“薛定谔的猫”
    • JavaScript 里的 ... 到底在搞什么鬼
    • 扩展运算符:把东西“炸开”的六脉神剑
      • 1. 数组复制——告别“引用陷阱”的绿茶
      • 2. 拼接数组——一行代码搞定“数组合并”
      • 3. 函数调用时“炸开”——代替 apply 的老寒腿
      • 4. 对象合并——“对象版乐高”
    • Rest 参数:把东西“收拢”的乾坤袋
      • 1. 写个求和函数——想传几个传几个
      • 2. 和解构搭配——“提取剩余”的骚操作
      • 3. 对象里也能 rest——“剔除敏感字段”神器
      • 4. 函数参数“收拢”之后,arguments 可以退休了
    • 合并对象时的坑:浅拷贝、顺序、Symbol 全给你摆明白
      • 1. 浅拷贝翻车现场
      • 2. 属性覆盖顺序实验
      • 3. Symbol 键会不会丢?
    • 函数参数太多?Rest 一招鲜,代码立马清爽
    • 遇到 Bug 别慌:排查思路来了
      • 1. 展开对象报错?先查浏览器版本
      • 2. 扩展 null/undefined 会炸?
      • 3. rest 放中间?引擎直接掀桌子
    • 开发老鸟私藏技巧
      • 1. 一行去重(Set + 扩展)
      • 2. 提取“除了前两个以外的所有参数”
      • 3. React 传 props——香还是坑?
      • 4. 性能敏感场景慎用扩展
    • 你以为你懂了?来几个反直觉的例子测测你
      • 1. 函数定义是 rest,但调用时我塞了个数组?
      • 2. `{...obj}` 和 `Object.assign({}, obj)` 真的一样吗?
      • 3. 箭头函数里能用 rest 吗?当然能,但注意 this 已经挂掉了
    • 结尾再啰嗦两句

扩展运算符 vs Rest 参数:前端新人别再傻傻分不清了!

——深夜群聊语音转文字,想到哪儿说到哪儿,别嫌我嘴碎


先甩一句狠话:… 这三个点,就是前端界的“薛定谔的猫”

没看源码之前,你以为它只是一个省略号;看完源码之后,你发现它一会儿是“炸开”的 TNT,一会儿是“打包”的麻袋。
最骚的是,它俩长得一毛一样,连亲妈(V8)都靠位置才分得清。
所以,今天咱们不背八股文,直接撸袖子开干,边骂边学,学完还分不清,你来成都请我吃火锅——辣到失忆算我的。


JavaScript 里的 … 到底在搞什么鬼

先给你一张“身份证”,记住就完事儿:

  • 出现在定义阶段(函数签名、解构赋值左边)→ Rest 参数,收破烂的。
  • 出现在调用阶段(函数调用、字面量右边)→ 扩展运算符,炸碉堡的。
// 收破烂functioncollectTrash(...args){// args 是真·数组console.log('今天收的破烂:',args);}// 炸碉堡consta=[1,2];constb=[0,...a,3];// [0,1,2,3]

就这么简单。
记不住?那就背口诀:“定义收,调用炸”
再记不住?那你把口诀抄屏保,老板看见还以为你多爱工作。


扩展运算符:把东西“炸开”的六脉神剑

1. 数组复制——告别“引用陷阱”的绿茶

constgirls=['小A','小B'];constbackupGirls=[...girls];// 真·克隆,不是影子分身backupGirls.push('小C');console.log(girls);// ['小A','小B'] 原数组稳如老狗

注意:浅拷贝!浅拷贝!浅拷贝!
重要的事吼三遍。如果数组里套对象,对象还是同一个地址,改了就一起翻车。

constteam=[{name:'张三',salary:10}];constteamCopy=[...team];teamCopy[0].salary=20;console.log(team[0].salary);// 20,张三的工资一起涨,老板哭晕

2. 拼接数组——一行代码搞定“数组合并”

constfront=['Angular','React'];constback=['Nest','Express'];constfullStack=[...front,'Docker',...back];console.log(fullStack);// ["Angular","React","Docker","Nest","Express"]

3. 函数调用时“炸开”——代替 apply 的老寒腿

constnums=[3,6,1];// 老写法Math.max.apply(null,nums);// 6// 新写法Math.max(...nums);// 6,语义清晰,不绕弯子

4. 对象合并——“对象版乐高”

constcommon={url:'/api',timeout:5000};constdev={url:'/dev-api',debug:true};constprod={url:'/prod-api',retry:3};// 后面属性会覆盖前面constconfig={...common,...dev};// dev 生效constfinal={...config,...prod};// prod 生效console.log(final);

坑点播报

  • 同名属性,后出现的 wins
  • 只遍历可枚举自身属性,Symbol 不会丢,但原型链上的拜拜;
  • 依旧是浅拷贝,嵌套对象请自重。

Rest 参数:把东西“收拢”的乾坤袋

1. 写个求和函数——想传几个传几个

functionsumAll(...numbers){// numbers 是真·数组,能直接 pop、map、forEachreturnnumbers.reduce((a,b)=>a+b,0);}console.log(sumAll(1,2,3));// 6console.log(sumAll());// 0,空数组也不会炸

2. 和解构搭配——“提取剩余”的骚操作

const[host,...others]=[22,33,44,55];console.log(host);// 22console.log(others);// [33,44,55]

3. 对象里也能 rest——“剔除敏感字段”神器

constuser={pwd:'123456',age:18,name:'狗蛋'};const{pwd,...safeUser}=user;sendToClient(safeUser);// pwd 被过滤掉,安全+1

4. 函数参数“收拢”之后,arguments 可以退休了

functionoldWay(){console.log(arguments);// 类数组,没 map 没 filter,难受}newWay(...args){console.log(args);// 真数组,想怎么撸怎么撸}

合并对象时的坑:浅拷贝、顺序、Symbol 全给你摆明白

1. 浅拷贝翻车现场

constsettings={theme:{color:'blue'}};constnewSet={...settings};newSet.theme.color='red';console.log(settings.theme.color);// red,原对象被连带

解决方案:深拷贝请用structuredClone、lodash 克隆函数,或者手写递归,别把扩展运算符当万能胶。

2. 属性覆盖顺序实验

consta={x:1};constb={x:2};constc={...a,...b};// x:2 胜出constd={...b,...a};// x:1 胜出

结论位置靠后的赢,跟 CSS 优先级一个德行。

3. Symbol 键会不会丢?

constkey=Symbol('id');constobj={[key]:666,name:'test'};constclone={...obj};console.log(clone[key]);// 666,还在,放心

函数参数太多?Rest 一招鲜,代码立马清爽

业务代码经常遇到“配置一堆”的鬼需求:

functionlog(level,prefix,...msgs){conststr=msgs.map(i=>`[${prefix}]${i}`).join('\n');console[level](str);}log('warn','订单模块','订单001超时','订单002缺货','订单003被用户骂了');

想加字段?...msgs全接住,后面想怎么玩怎么玩,再也不用数形参个数
再说一遍:rest 必须放最后,否则引擎直接甩脸报错:

functionbad(a,...b,c){}// SyntaxError:Rest parameter must be last formal parameter

遇到 Bug 别慌:排查思路来了

1. 展开对象报错?先查浏览器版本

扩展运算符进 ECMAScript 2018(对象部分),老 IE 肯定跑不动。
生产环境报 “Unexpected token ‘…’”?九成是 Webpack 没配 Babel,或者 browserslist 把 IE 11 漏了。
兜底写法

constclone=typeofstructuredClone==='function'?structuredClone(obj):JSON.parse(JSON.stringify(obj));// 糙但快

2. 扩展 null/undefined 会炸?

constdata=null;constwrap={...data};// 不会报错,只是啥也没有// 但数组展开就凉了:constarr=[...null];// TypeError: null is not iterable

优雅兜底

constsafeArr=[...(data||[])];constsafeObj={...(data||{})};

3. rest 放中间?引擎直接掀桌子

上面演示过了,再写一遍加深印象:

functionf(a,...rest,b){}// 语法错误,直接红屏

开发老鸟私藏技巧

1. 一行去重(Set + 扩展)

constdup=[1,2,2,3];constunique=[...newSet(dup)];// [1,2,3]

Set 去重效率接近 O(n),短数组看不出,上万条数据时真香

2. 提取“除了前两个以外的所有参数”

functionformat(time,user,...args){// args 就是“其他字段”,想怎么拼接怎么拼接return{time,user,comments:args};}

3. React 传 props——香还是坑?

<MyButton{...props}type="primary"/>

好处:写起来爽;:会把所有字段都灌进去,DOM 透传非标准属性会报警告。
解决方案

const{type,children,...rest}=props;return<button className={type}{...rest}>{children}</button>;

只把合法属性往下扔,既优雅又不挨骂

4. 性能敏感场景慎用扩展

扩展运算符每次都会生成新对象/新数组,在 React 渲染、大数据列表里随手一写,内存蹭蹭涨
实测 10w 条记录做...合并,Chrome 性能面板直接飙红。
优化思路

  • 用immer做突变草稿,写完一次性不可变化;
  • 或者上结构共享库(immutable-js、mutative),别让 GC 陪你加班。

你以为你懂了?来几个反直觉的例子测测你

1. 函数定义是 rest,但调用时我塞了个数组?

functionfoo(...args){console.log(args);// 二维数组!}foo([1,2,3]);// 输出:[[1,2,3]]

解析:rest 不管三七二十一,把所有实参打包成数组
你传一个数组,它就把这个数组当成第一个元素,整包收走

2.{...obj}Object.assign({}, obj)真的一样吗?

  • 前者不会触发 setter;后者会。
  • 前者无法拷贝属性访问器(getter/setter);后者可以。
  • 前者少一次函数调用,理论上更快(可忽略)。
consto={getx(){console.log('getter跑啦');return1;}};consta={...o};// 啥也没打印constb=Object.assign({},o);// 打印:getter跑啦

3. 箭头函数里能用 rest 吗?当然能,但注意 this 已经挂掉了

constarrow=(...items)=>items.length;console.log(arrow(1,2,3));// 3

箭头函数没有自己的argumentsrest 是唯一的“收拢”选择,也算被迫营业。


结尾再啰嗦两句

别光顾着收藏,动手敲十遍,肌肉记忆才是你的
明天面试再被问到 “扩展和 rest 区别”,你就把这篇文章背()一遍,边背边比划手势
左手张开——“炸开”;右手握拳——“收拢”。
面试官要是还听不懂,你就说:“来,我现场写给你看。”
然后甩出上面任意一段代码,offer 基本稳了

好了,我去撸串了,键盘上都是孜然味。
你啥时候彻底分清了,群里吼一声,我请你喝阔落。

欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。

推荐:DTcode7的博客首页。
一个做过前端开发的产品经理,经历过睿智产品的折磨导致脱发之后,励志要翻身农奴把歌唱,一边打入敌人内部一边持续提升自己,为我们广大开发同胞谋福祉,坚决抵制睿智产品折磨我们码农兄弟!


专栏系列(点击解锁)学习路线(点击解锁)知识定位
《微信小程序相关博客》持续更新中~结合微信官方原生框架、uniapp等小程序框架,记录请求、封装、tabbar、UI组件的学习记录和使用技巧等
《AIGC相关博客》持续更新中~AIGC、AI生产力工具的介绍,例如stable diffusion这种的AI绘画工具安装、使用、技巧等总结
《HTML网站开发相关》《前端基础入门三大核心之html相关博客》前端基础入门三大核心之html板块的内容,入坑前端或者辅助学习的必看知识
《前端基础入门三大核心之JS相关博客》前端JS是JavaScript语言在网页开发中的应用,负责实现交互效果和动态内容。它与HTML和CSS并称前端三剑客,共同构建用户界面。
通过操作DOM元素、响应事件、发起网络请求等,JS使页面能够响应用户行为,实现数据动态展示和页面流畅跳转,是现代Web开发的核心
《前端基础入门三大核心之CSS相关博客》介绍前端开发中遇到的CSS疑问和各种奇妙的CSS语法,同时收集精美的CSS效果代码,用来丰富你的web网页
《canvas绘图相关博客》Canvas是HTML5中用于绘制图形的元素,通过JavaScript及其提供的绘图API,开发者可以在网页上绘制出各种复杂的图形、动画和图像效果。Canvas提供了高度的灵活性和控制力,使得前端绘图技术更加丰富和多样化
《Vue实战相关博客》持续更新中~详细总结了常用UI库elementUI的使用技巧以及Vue的学习之旅
《python相关博客》持续更新中~Python,简洁易学的编程语言,强大到足以应对各种应用场景,是编程新手的理想选择,也是专业人士的得力工具
《sql数据库相关博客》持续更新中~SQL数据库:高效管理数据的利器,学会SQL,轻松驾驭结构化数据,解锁数据分析与挖掘的无限可能
《算法系列相关博客》持续更新中~算法与数据结构学习总结,通过JS来编写处理复杂有趣的算法问题,提升你的技术思维
《IT信息技术相关博客》持续更新中~作为信息化人员所需要掌握的底层技术,涉及软件开发、网络建设、系统维护等领域的知识
《信息化人员基础技能知识相关博客》无论你是开发、产品、实施、经理,只要是从事信息化相关行业的人员,都应该掌握这些信息化的基础知识,可以不精通但是一定要了解,避免日常工作中贻笑大方
《信息化技能面试宝典相关博客》涉及信息化相关工作基础知识和面试技巧,提升自我能力与面试通过率,扩展知识面
《前端开发习惯与小技巧相关博客》持续更新中~罗列常用的开发工具使用技巧,如 Vscode快捷键操作、Git、CMD、游览器控制台等
《photoshop相关博客》持续更新中~基础的PS学习记录,含括PPI与DPI、物理像素dp、逻辑像素dip、矢量图和位图以及帧动画等的学习总结
日常开发&办公&生产【实用工具】分享相关博客》持续更新中~分享介绍各种开发中、工作中、个人生产以及学习上的工具,丰富阅历,给大家提供处理事情的更多角度,学习了解更多的便利工具,如Fiddler抓包、办公快捷键、虚拟机VMware等工具

吾辈才疏学浅,摹写之作,恐有瑕疵。望诸君海涵赐教。望轻喷,嘤嘤嘤

非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。愿斯文对汝有所裨益,纵其简陋未及渊博,亦足以略尽绵薄之力。倘若尚存阙漏,敬请不吝斧正,俾便精进!

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

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

立即咨询