前言
在写代码时常常会使用
...xx
这种用法,有时叫它展开运算符
,有时又叫剩余参数运算符
,感觉有点乱,究其原因是自己理解不够清晰,下面简单记录一下🐳
在定义函数
的时候使用运算符(...),会将传过来的多余参数合到一起
剩余参数永远是个数组
,即使没有值,也是空数组
剩余参数只能作为最后
一个参数
const fn = (num1, num2, ...nums) => { console.log(num1, num2, nums); }; fn(1, 2); // 1 2 [] fn1(1, 2, 3, 4, 5, 6); // 1 2 [3,4,5,6]
const arr = ["css", "js", "ts", "vue"]; console.log(...arr); // css js ts vue
剩余参数
运算符:1,3,5 --> [1,3,5]
展开
运算符:[1,3,5] --> 1,3,5
const diff = (...args) => { console.log(args); // 剩余参数运算符:[1,3,5] console.log(...args); // 展开运算符:1,3,5 }; diff(1, 3, 5);
const citys = ["南京", "北京", "上海", "成都", "杭州"]; const citysCopy = [...citys]; console.log(citysCopy); // ["南京", "北京", "上海", "成都", "杭州"]
const colors = ["red", "orange", "yellow", "green", "orange"]; const onlyColors = [...new Set(colors)]; console.log(onlyColors); // ["red", "orange", "yellow", "green"]
const animals = ["cat", "dog"]; const seasons = ["spring", "summer"]; const animalsAndSeasons = [...animals, ...seasons]; console.log(animalsAndSeasons); // ["cat", "dog", "spring", "summer"]
const digitals = ["pc", "watch", "camera", "keyboard", "mouse"]; const [pc, ...otherDigitals] = digitals; console.log(otherDigitals); // ["watch", "camera", "keyboard", "mouse"]
等于
形参个数:一一对应小于
形参个数:缺少值为 undefined大于
形参个数:多的参数值被忽略调用函数
的时候使用运算符(...),会把原本聚拢在一起的数据拆分
传递给各个参数const phone1 = ["apple", "vivo", "oppo"]; const phone2 = ["apple", "vivo"]; const phone3 = ["apple", "vivo", "oppo", "华为"]; const mixer = (brand1, brand2, brand3) => { console.log(brand1, brand2, brand3); }; mixer(...phone1); // 等于:一一对应,apple vivo oppo mixer(...phone2); // 小于:缺少值为undefined,apple vivo undefined mixer(...phone3); // 多于:多的参数值被忽略,apple vivo oppo
const argsTransformArr = (...args) => console.log(args); argsTransformArr("pineapple"); // ["pineapple"] argsTransformArr(66, 88, 99); // [66, 88, 99]
const student = { name: "Jack", school: { class: "Software Engineering Class 2" } }; const studentCopy = { ...student }; console.log(studentCopy); // {name: "Jack",school:{class: "Software Engineering Class 3"}}
所有属性
const personName = { name: "nina" }; const personSex = { sex: "female" }; const personAge = { age: 18 }; const person = { ...personName, ...personSex, ...personAge }; console.log(person); // {name: "nina", sex: "female", age: 18}
同名的属性
,则后面对象中的属性值覆盖
前面的同名的属性值const fruit1 = { name: "apple", color: "red" }; const fruit2 = { name: "strawberry", weight: "20g" }; const fruit = { ...fruit1, ...fruit2 }; console.log(fruit); // {name: "strawberry", color: "red", weight: "20g"}
const fruit3 = { detail: { name: "apple", size: "big", weight: "300g" } }; console.log({ ...fruit3 });
空对象
,则仍然是空对象不是对象
,则会自动将其转为对象,但是新创建的对象由于并不包含任何属性
,故为空对象console.log({ ...{} }); // {} console.log({ ...1 }); // {} console.log({ ...undefined }); // {} console.log({ ...null }); // {} console.log({ ...true }); // {}
const tableData1 = { list: [ { name: "张三", address: "南京" }, { name: "李四", address: "北京" } ], pageSize: 10, pageNum: 1 }; const tableData2 = { list: [ { name: "王五", address: "深圳" }, { name: "赵六", address: "上海" } ], pageSize: 20, pageNum: 2 }; const allTableDate = { ...tableData1, list: [...tableData1.list, ...tableData2.list] }; console.log(allTableDate);
const name = "Song"; console.log(...name); // 直接展开,S o n g console.log([...name]); // 数组形式展开,["S", "o", "n", "g"] console.log({ ...name }); // 对象形式展开,{0: "S", 1: "o", 2: "n", 3: "g"}
数组
,值类型
的属性被深度拷贝
了(用的不同对象
),而引用类型的属性只是做了浅拷贝
(复制的为引用地址
,引用对象并未复制,即用的是同一个对象
)// 值类型 const citys = ["南京", "北京", "上海", "成都", "杭州"]; const citysCopy = [...citys]; citys[0] = "深圳"; console.log(citysCopy); // ["南京", "北京", "上海", "成都", "杭州"]
// 引用类型 let users = [ { name: "小红", sex: "female" }, { name: "小明", sex: "male" } ]; let usersCopy = [...users]; users[0].name = "小花"; console.info(usersCopy);
对象
,值类型
的属性被深度拷贝
了(用的不同对象
),而引用类型的属性只是做了浅拷贝
(复制的为引用地址
,引用对象并未复制,即用的是同一个对象
)let user = { name: "张三", sex: "男", address: { city: "北京" } }; let clonedUser = { ...user }; user.name = "李四"; user.address.city = "四川"; console.log(user); console.log(clonedUser);
如有错误或遗漏,欢迎批评指正🌝
源码截图
源码获取:关注公众号「码农园区」,回复 【源码】,即可获取全套源码下载链接