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())方法,利用展开语法也是一个很不错的选择。

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

相关推荐
IT女孩儿37 分钟前
JavaScript--WebAPI查缺补漏(二)
开发语言·前端·javascript·html·ecmascript
@解忧杂货铺5 小时前
前端vue如何实现数字框中通过鼠标滚轮上下滚动增减数字
前端·javascript·vue.js
真的很上进10 小时前
如何借助 Babel+TS+ESLint 构建现代 JS 工程环境?
java·前端·javascript·css·react.js·vue·html
噢,我明白了13 小时前
同源策略:为什么XMLHttpRequest不能跨域请求资源?
javascript·跨域
sanguine__13 小时前
APIs-day2
javascript·css·css3
关你西红柿子14 小时前
小程序app封装公用顶部筛选区uv-drop-down
前端·javascript·vue.js·小程序·uv
济南小草根14 小时前
把一个Vue项目的页面打包后再另一个项目中使用
前端·javascript·vue.js
小木_.14 小时前
【python 逆向分析某有道翻译】分析有道翻译公开的密文内容,webpack类型,全程扣代码,最后实现接口调用翻译,仅供学习参考
javascript·python·学习·webpack·分享·逆向分析
Aphasia31115 小时前
一次搞懂 JS 对象转换,从此告别类型错误!
javascript·面试
m0_7482565615 小时前
Vue - axios的使用
前端·javascript·vue.js