JavaScript展开语法

JavaScript 每日一篇,记录自学JavaScript语言的点点滴滴。

MDN 官网上对于JavaScript展开语法的解释:

developer.mozilla.org/zh-CN/docs/...

在ES6版的JavaScript发布之前,要想在数组内增加元素,或将两个数组合并;我们必须具体声明数组元素的内容和索引。

ini 复制代码
const arr = [7, 8, 9];
const badNewArr = [1, 2, arr[0], arr[1], arr[2]];
console.log('badNewArr: ', badNewArr);

通过展开语法...将两个数组的元素进行合并

现在如果想让arr数组和newArr数组进行合并,你只需在需要合并的数组前加上...即可将两个数组合并成一个数组并赋值给newArr

ini 复制代码
const arr = [7, 8, 9];
const newArr = [1, 2, ...arr];
console.log('newArr: ', newArr);

通过这种方式合并两个数组的内容不仅可以降低数组元素引用的错误,还可以提高代码的可读性。

其次,如果你好奇想查看一下...newArr输出了什么结果,你会惊奇的发现,...newArrconsole.log(1, 2, 7, 8, 9);都输出的形式一样,两者在内存中实际上是同一种数据类型。

ini 复制代码
let a = console.log(...newArr);
let b = console.log(1, 2, 7, 8, 9);
console.log(a === b);

当然这种数组展开语法方式也可以应用到对象数组上,通过浅拷贝创建一个数组的副本。

arduino 复制代码
const restaurant = {
    name: '意大利🇮🇹经典',
    location: 'Via Angelo Tavanti 23, 佛罗伦萨, 意大利',
    categories: ['意大利', '比萨店', '素食', '有机'],
    starterMenu: ['佛卡夏', '意式烤面包', '大蒜面包', '卡普雷塞沙'],
    mainMenu: ['披萨', '意大利面', '烩饭'],
};
const newMenu = [...restaurant.mainMenu, '汤圆Gnocci'];
console.log(newMenu);

通过数组展开语法...复制一个和restaurant对象下的mainMenu属性内相同的数组。

arduino 复制代码
// 通过浅拷贝创建一个数组
const mainMenuCopy = [...restaurant.mainMenu];
console.log('mainMenuCopy: ', mainMenuCopy);

连接🔗两个数组:

arduino 复制代码
// 🔗连接两个数组
console.log('restaurant.mainMenu: ', restaurant.mainMenu);
console.log('restaurant.starterMenu: ', restaurant.starterMenu);
const menu = [...restaurant.starterMenu, ...restaurant.mainMenu];
console.log(menu);

通过展开语法...将字符串拆成单个字符

利用展开语法分解字符串中的字符,会返回一个由字符元素组成的数组并赋值给letters变量。

ini 复制代码
// 利用展开语法分解字符串中的字符
const str = 'yukon';
const letters = [...str, '', 'S.'];
console.log(letters);
console.log(...str);

⚠️注意:展开语法仅限于函数参数接收多个输入,或构建一个新数组。不要在模版字符串或其他函数中(如typeof())使用它,否则程序会返回一个错误,并中断程序。例如下面这个例子:

ini 复制代码
const str = 'yukon';
const letters = [...str, '', 'S.'];
console.log(letters);
console.log(...str);
// 使用展开语法仅限于函数参数接收多个输入,或构建一个新数组时会用到
console.log(`${...str} Geegin`);    // Error

另外,在JavaScript中可以对具有迭代类型的对象和函数使用展开语法。例如数组(Array)字符串(String)map集合set()可以使用展开语法...,注意不能对非迭代对象和函数使用展开语法...,否则可能会产生程序错误🙅。

使用展开语法...完成一个真实的项目

让我们修改对象,在原本对象的基础上增加一个点餐总结方法。在用户输入完要点的餐品后,把输入的输出到控制台上。

首先在restaurant对象内创建orderPasta方法。并将ing变量作为此方法的输入参数。

arduino 复制代码
const restaurant = {
    name: '意大利🇮🇹经典',
    location: 'Via Angelo Tavanti 23, 佛罗伦萨, 意大利',
    categories: ['意大利', '比萨店', '素食', '有机'],
    starterMenu: ['佛卡夏', '意式烤面包', '大蒜面包', '卡普雷塞沙'],
    mainMenu: ['披萨', '意大利面', '烩饭'],
    openingHours: {
        thu: {
            open: 12,
            close: 22,
        },
        fri: {
            open: 11,
            close: 23,
        },
        sat: {
            open: 0, // Open 24 hours
            close: 24,
        },
    },

    orderPasta: function (ing1, ing2, ing3) {
        console.log(`这是你最喜欢的${ing1},${ing2},${ing3}烩饭`);
    }
};

为了更加贴近用户的输入数据的方式,这里使用浏览器BOM的prompt框来接收用户的输入。在过去的老版本中,用户输入完菜品后,需要依次调用ingredients数组对应的索引。但如果你使用了ES6全新的方法,你可以直接使用展开语法即可调用ingredients数组内的全部内容。

rust 复制代码
// Real-world Example
const ingredients = [prompt('Let's make pasta! Ingredient 1 让我们做意大利面吧🍝 佐料一🍜'),
prompt('Ingredient 2 佐料二🧂'), prompt('Ingredient 3 佐料三🍅'),]
console.log(ingredients);

// INPUT: mashroom, aspargus, cheese or 黄瓜 番茄 奶酪
// Old way
restaurant.orderPasta(ingredients[0], ingredients[1], ingredients[2]);
// New way in ES6
restaurant.orderPasta(...ingredients);

大多数JavaScript中的元素都是可迭代的,但是对象除外。

另外展开语法语法...同样可以对对象做操作

arduino 复制代码
const restaurant = {
    name: '意大利🇮🇹经典',
    location: 'Via Angelo Tavanti 23, 佛罗伦萨, 意大利',
    categories: ['意大利', '比萨店', '素食', '有机'],
    starterMenu: ['佛卡夏', '意式烤面包', '大蒜面包', '卡普雷塞沙'],
    mainMenu: ['披萨', '意大利面', '烩饭'],
    openingHours: {
        thu: {
            open: 12,
            close: 22,
        },
        fri: {
            open: 11,
            close: 23,
        },
        sat: {
            open: 0, // Open 24 hours
            close: 24,
        },
    },

    orderPasta: function (ing1, ing2, ing3) {
        console.log(`这是你最喜欢的${ing1},${ing2},${ing3}烩饭`);
    }
};
ini 复制代码
const newRestaurant = { foundedIn: 1998, ...restaurant, founder: '古商祺' }
console.log(newRestaurant);

通过展开语法,不仅可以将对象restaurant中的属性和内容复制到newRestaurant对象中,还可以同时加入多个不同的属性到newRestaurant对象中。这种方式相当于对restaurant对象进行了继承操作;在保留restaurant属性值不变的情况下添加了不同的属性,从而形成了newRestaurant对象。

另外扩展语法还经常被用于对象的复制。并且通过扩展语法复制出的对象实际上是对目标对象的深拷贝,并非简单的为对象(使用Object.assign()方法)创建一个副本。例如下面这个例子🌰,利用展开语法将对象restaurant中的属性和值全部复制到了restaurantCopy对象中。接着单独对刚刚复制的对象restaurantCopy下的name属性命名为Ristorante Roma。你会发现restaurantCopy下的namerestaurant下的name并不是一个。这证明通过展开语法复制出的对象是一种深拷贝。

ini 复制代码
const restaurantCopy = { ...restaurant };
restaurantCopy.name = 'Ristorante Roma';
console.log('restaurantCopy: ', restaurantCopy);
console.log('restaurant: ', restaurant);
console.log('restaurantCopy.name: ', restaurantCopy.name);
console.log('restaurant.name: ', restaurant.name);

所以,对象深拷贝不仅可以使用JSON.parse(JSON.stringify())方法,利用展开语法也是一个很不错的选择。

欢迎大家评论指教,一起学习,一起进步!

相关推荐
Martin -Tang1 小时前
Vue 3 中,ref 和 reactive的区别
前端·javascript·vue.js
FakeOccupational3 小时前
nodejs 020: React语法规则 props和state
前端·javascript·react.js
放逐者-保持本心,方可放逐3 小时前
react 组件应用
开发语言·前端·javascript·react.js·前端框架
曹天骄4 小时前
next中服务端组件共享接口数据
前端·javascript·react.js
郝晨妤6 小时前
鸿蒙ArkTS和TS有什么区别?
前端·javascript·typescript·鸿蒙
喝旺仔la6 小时前
vue的样式知识点
前端·javascript·vue.js
别忘了微笑_cuicui6 小时前
elementUI中2个日期组件实现开始时间、结束时间(禁用日期面板、控制开始时间不能超过结束时间的时分秒)实现方案
前端·javascript·elementui
尝尝你的优乐美6 小时前
vue3.0中h函数的简单使用
前端·javascript·vue.js
windy1a6 小时前
【C语言】js写一个冒泡顺序
javascript
会发光的猪。7 小时前
如何使用脚手架创建一个若依框架vue3+setup+js+vite的项目详细教程
前端·javascript·vue.js·前端框架