ES6扩展运算符——三个点(...)用法详解

目录

1  含义

2  替代数组的 apply 方法

3  扩展运算符的应用

( 1 )合并数组

( 2 )与解构赋值结合

( 3 )函数的返回值

( 4 )字符串

( 5 )实现了 Iterator 接口的对象

( 6 ) Map 和 Set 结构, Generator 函数


 

1  含义

扩展运算符( spread )是三个点(...)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。 ——参考:【JS高级】ES6_剩余参数、打散数组-CSDN博客

console.log(...[1, 2, 3])
// 1 2 3
console.log(1, ...[2, 3, 4], 5)
// 1 2 3 4 5
[...document.querySelectorAll('div')]
// [<div>, <div>, <div>]

该运算符主要用于函数调用。

var array=[1,2,3,4,5]
var items=[6,7]
function push(array, ...items) {
array.push(...items);
}
push(array,...items) // 9 返回数组的长度

function add(x, y) {
return x + y;
}
var numbers = [4, 38];
add(...numbers) // 42

上面代码中,array.push(...items)和add(...numbers)这两行,都是函数的调用,它们的都使用了扩展运算符。该运算符将一个数组,变为参数序列。

扩展运算符与正常的函数参数可以结合使用,非常灵活。

function f(v, w, x, y, z) {
    return v + w + x + y + z
 }
var args = [0, 1];
f(-1, ...args, 2, ...[3]); // 5

2  替代数组的 apply 方法

由于扩展运算符可以展开数组,所以不再需要apply方法,将数组转为函数的参数了。

// ES5 的写法
function f(x, y, z) {
    return x + y + z
}
var args = [0, 1, 2];
f.apply(null, args); // 3

// ES6 的写法
function f(x, y, z) {
    return x + y + z
}
var args = [0, 1, 2];
f(...args); // 3

下面是扩展运算符取代apply方法的一个实际的例子,应用Math.max方法,简化求出一个数组最大元素的写法。

// ES5 的写法
Math.max.apply(null, [14, 3, 77]); // 77

// ES6 的写法
Math.max(...[14, 3, 77]); // 77

//  等同于
Math.max(14, 3, 77); // 77

// Math.max()以及Math.min(),不能直接传入一个数组,因为它们不支持获得数组中的最大值或最小值

上面代码表示,由于 JavaScript 不提供求数组最大元素的函数,所以只能套用Math.max函数,将数组转为一个参数序列,然后求最大值。有了扩展运算符以后,就可以直接用Math.max了。

另一个例子是通过push函数,将一个数组添加到另一个数组的尾部。

// ES5 的写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
Array.prototype.push.apply(arr1, arr2); // 6 数组的push方法,返回数组的长度

// ES6 的写法
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2); // 6 数组的push方法,返回数组的长度

上面代码的 ES5 写法中,push方法的参数不能是数组,所以只好通过apply方法变通使用push方法。有了扩展运算符,就可以直接将数组传入push方法。

下面是另外一个例子。

// ES5
new (Date.bind.apply(Date, [null, 2024, 2, 2]))

// ES6
new Date(...[2024, 2, 2]);

3  扩展运算符的应用

( 1 )合并数组

扩展运算符提供了数组合并的新写法。

// ES5
[1, 2].concat(more)
// ES6
[1, 2, ...more]
var arr1 = ['a', 'b'];
var arr2 = ['c'];
var arr3 = ['d', 'e'];
// ES5 的合并数组
arr1.concat(arr2, arr3);
// [ 'a', 'b', 'c', 'd', 'e' ]
// ES6 的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]

( 2 )与解构赋值结合

扩展运算符可以与解构赋值结合起来,用于生成数组。

// ES5
a = list[0], rest = list.slice(1) // slice 数组的截取方法
// ES6
[a, ...rest] = list

// 下面是另外一些例子。
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest // [2, 3, 4, 5]

const [first, ...rest] = [];
first // undefined
rest // []:

const [first, ...rest] = ["foo"];
first // "foo"
rest // []

如果将扩展运算符用于数组赋值,只能放在参数的最后一位,否则会报错。

const [...butLast, last] = [1, 2, 3, 4, 5];
//  报错:Uncaught SyntaxError: Rest element must be last element
const [first, ...middle, last] = [1, 2, 3, 4, 5];
//  报错:Uncaught SyntaxError: Rest element must be last element

( 3 )函数的返回值

JavaScript 的函数只能返回一个值,如果需要返回多个值,只能返回数组或对象。扩展运算符提供了解决这个问题的一种变通方法。

var dateFields = readDateFields(database);
var d = new Date(...dateFields);

上面代码从数据库取出一行数据,通过扩展运算符,直接将其传入构造函数Date。

( 4 )字符串

扩展运算符还可以将字符串转为真正的数组。

[...'hello'] // [ "h", "e", "l", "l", "o" ]

上面的写法,有一个重要的好处,那就是能够正确识别 32 位的 Unicode 字符。

'x\uD83D\uDE80y'.length // 4
[...'x\uD83D\uDE80y'].length // 3

上面代码的第一种写法, JavaScript 会将 32 位 Unicode 字符,识别为 2 个字符,采用扩展运算符就没有这个问题。因此,正确返回字符串长度的函数,可以像下面这样写。

function length(str) {
return [...str].length;
}
length('x\uD83D\uDE80y') // 3

凡是涉及到操作 32 位 Unicode 字符的函数,都有这个问题。因此,最好都用扩展运算符改写。

let str = 'x\uD83D\uDE80y';
str.split('').reverse().join('')
// 'y\uDE80\uD83Dx'
[...str].reverse().join('')
// 'y\uD83D\uDE80x'

上面代码中,如果不用扩展运算符,字符串的reverse操作就不正确。

( 5 )实现了 Iterator 接口的对象

任何 Iterator 接口的对象,都可以用扩展运算符转为真正的数组。

var nodeList = document.querySelectorAll('div');
var array = [...nodeList];

上面代码中,querySelectorAll方法返回的是一个nodeList对象。它不是数组,而是一个类似数组的对象,即类数组对象。这时,扩展运算符可以将其转为真正的数组,原因就在于NodeList对象实现了 Iterator 接口。

对于那些没有部署 Iterator 接口的类似数组的对象,扩展运算符就无法将其转为真正的数组。

let arrayLike = {
'0': 'a',
'1': 'b',
'2': 'c',
length: 3
};
// TypeError: Cannot spread non-iterable object.
let arr = [...arrayLike]; // TypeError: arrayLike is not iterable


// 使用Array.from方法将arrayLike转为真正的数组,方可是扩展运算符
let Arr =Array.from(arrayLike);
let newArr =[...Arr];
console.log(newArr); // ['a', 'b', 'c']

上面代码中,arrayLike是一个类似数组的对象,但是没有部署 Iterator 接口,扩展运算符就会报错。这时,可以改为使用Array.from方法将arrayLike转为真正的数组。

( 6 ) Map 和 Set 结构, Generator 函数

扩展运算符内部调用的是数据结构的 Iterator 接口,因此只要具有 Iterator 接口的对象,都可以使用扩展运算符,比如 Map 结构

let map = new Map([
[1, 'one'],
[2, 'two'],
[3, 'three'],
]);
let arr = [...map.keys()]; // [1, 2, 3]

Generator 函数运行后,返回一个遍历器对象,因此,也可以使用扩展运算符。

参考:ES6 新增函数类型——Generator 函数使用方法详解

var go = function*(){
yield 1;
yield 2;
yield 3;
};
[...go()] // [1, 2, 3]

上面代码中,变量go是一个 Generator 函数,执行后返回的是一个遍历器对象,对这个遍历器对象执行扩展运算符,就会将内部遍历得到的值,转为一个数组。

如果对没有iterator接口的对象,使用扩展运算符,将会报错。

var obj = {a: 1, b: 2};
// TypeError: obj is not iterable
let arr = [...obj]; // TypeError: Cannot spread non-iterable object

参考资料

展开语法 - JavaScript | MDN | 剩余参数 - JavaScript | MDN

JavaScript展开运算符和剩余运算符的区别详解_javascript技巧_脚本之家

ES6 展开语法(...)与剩余参数-CSDN博客 | JavaScript中剩余参数的使用详解_脚本之家

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/375368.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Git基础命令,分支,标签的使用【快速入门Git】

Git基础命令&#xff0c;分支&#xff0c;标签的使用【快速入门Git】 Git基础常用命令Git工作流程工作区&#xff0c;暂存区和版本库文件状态获取Git仓库 git init | git clone查看文件状态 git status暂存已修改的文件 git add 查看已暂存和未暂存的修改 git diff提交文件更改…

数据结构——D/二叉树

&#x1f308;个人主页&#xff1a;慢了半拍 &#x1f525; 创作专栏&#xff1a;《史上最强算法分析》 | 《无味生》 |《史上最强C语言讲解》 | 《史上最强C练习解析》 &#x1f3c6;我的格言&#xff1a;一切只是时间问题。 ​ 1.树概念及结构 1.1树的概念 树是一种非线性的…

excel 导出 The maximum length of cell contents (text) is 32767 characters

导出excel报错。错误日志提示&#xff1a;:The maximum length of cell contents (text) is 32767 characters 排查后&#xff0c;发现poi有单元格最大长度校验&#xff0c;超过32767会报错。 解决方案&#xff1a; 通过java反射机制&#xff0c;设置单元格最大校验限制为Int…

【Git教程】(一)基本概念:—— 工作流、分布式版本控制、版本库 ~

Git教程 基本概念 1️⃣ 为什么要用 Git2️⃣ 为什么要用工作流3️⃣ 分布式版本控制4️⃣ 版本库5️⃣ 简单的分支创建与合并&#x1f33e; 总结 在本章中&#xff0c;将介绍一个分布式版本控制系统的设计思路&#xff0c;以及它与集中式版本控制系统的不同之处。除此之外&am…

鸿蒙开发-UI-组件导航-Tabs

鸿蒙开发-UI-组件 鸿蒙开发-UI-组件2 鸿蒙开发-UI-组件3 鸿蒙开发-UI-气泡/菜单 鸿蒙开发-UI-页面路由 鸿蒙开发-UI-组件导航-Navigation 文章目录 一、基本概念 二、导航 1.底部导航 2.顶部导航 3.侧边导航 4.导航栏限制滑动 三、导航栏 1.固定导航栏 2.滚动导航栏 3…

Verilog刷题笔记21

题目&#xff1a; A priority encoder is a combinational circuit that, when given an input bit vector, outputs the position of the first 1 bit in the vector. For example, a 8-bit priority encoder given the input 8’b10010000 would output 3’d4, because bit[4…

93.网游逆向分析与插件开发-游戏窗口化助手-升级经验数据获取的逆向分析

内容参考于&#xff1a;易道云信息技术研究院VIP课 上一个内容&#xff1a;显示游戏数据到小助手UI 码云地址&#xff08;游戏窗口化助手 分支&#xff09;&#xff1a;https://gitee.com/dye_your_fingers/sro_-ex.git 码云版本号&#xff1a;852c339f5e4c103390b123e0eaed…

Xampp中Xdebug的安装使用

工欲善其事&#xff0c;必先利其器 XDebug简介 XDebug 是一个用于 PHP 的调试和性能分析工具。它提供了一系列功能&#xff0c;帮助开发者在开发和调试 PHP 应用程序时更加高效。 以下是 XDebug 的一些主要特性和功能&#xff1a; 调试功能&#xff1a; 断点调试&#xff1a;…

Unity C#进阶案例 “泛型编程”

文章目录 泛型基础示例1&#xff1a;泛型类与方法示例2&#xff1a;泛型方法示例3&#xff1a;泛型约束示例4&#xff1a;泛型委托与事件示例5&#xff1a;泛型单例模式&#xff08;Unity&#xff09; 在Unity中&#xff0c;C#的泛型编程是一种强大的工具&#xff0c;它允许你编…

补题:leetcode第382场周赛 3022. 给定操作次数内使剩余元素的或值最小

3022. 给定操作次数内使剩余元素的或值最小 - 力扣&#xff08;LeetCode&#xff09; 拆位 n个数进行或运算的结果最小&#xff0c;每次操作可以对相邻的两个数进行与运算&#xff0c;至多进行k次操作 n个数进行或运算&#xff0c;可以对每个数进行拆解&#xff0c;拆解成最小…

RabbitMQ-3.发送者的可靠性

发送者的可靠性 3.发送者的可靠性3.1.生产者重试机制3.2.生产者确认机制3.3.实现生产者确认3.3.1.开启生产者确认3.3.2.定义ReturnCallback3.3.3.定义ConfirmCallback 3.发送者的可靠性 首先&#xff0c;我们一起分析一下消息丢失的可能性有哪些。 消息从发送者发送消息&#…

11.0 Zookeeper watcher 事件机制原理剖析

zookeeper 的 watcher 机制&#xff0c;可以分为四个过程&#xff1a; 客户端注册 watcher。服务端处理 watcher。服务端触发 watcher 事件。客户端回调 watcher。 其中客户端注册 watcher 有三种方式&#xff0c;调用客户端 API 可以分别通过 getData、exists、getChildren …

vulnhub中Beelzebub靶机

渗透思路 一.信息收集1.网段探测2.端口探测3.常见漏洞扫描4.目录扫描5.web页面分析 二.渗透继续目录扫描ssh连接提权提权&#xff0c;flag 一.信息收集 1.网段探测 ┌──(root㉿kali)-[~] └─# nmap -Pn 192.168.0.0/24 --min-rate 10000 Starting …

计算机科学导论(4)DMA传输原理

文章目录 DMA的工作原理DMA的优势DMA的类型DMA的应用 DMA&#xff08;Direct Memory Access&#xff09;直接内存访问是一种允许某些硬件子系统在不通过中央处理单元&#xff08;CPU&#xff09;的情况下&#xff0c;直接从内存读取或向内存写入数据的技术。这种方式可以显著提…

【OpenVINO™】在 MacOS 上使用 OpenVINO™ C# API 部署 Yolov5 (上篇)

在 MacOS 上使用 OpenVINO™ C# API 部署 Yolov5 &#xff08;上篇&#xff09; 项目介绍 YOLOv5 是革命性的 "单阶段"对象检测模型的第五次迭代&#xff0c;旨在实时提供高速、高精度的结果&#xff0c;是世界上最受欢迎的视觉人工智能模型&#xff0c;代表了Ult…

电力负荷预测 | 电力系统负荷预测模型(Python线性回归、随机森林、支持向量机、BP神经网络、GRU、LSTM)

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 电力系统负荷预测模型(Python线性回归、随机森林、支持向量机、BP神经网络、GRU、LSTM) 所谓预测,就是指通过对事物进行分析及研究,并运用合理的方法探索事物的发展变化规律,对其未来发展做出预先估计和判断。…

二叉树的锯齿形遍历,力扣

目录 题目&#xff1a; 我们直接看题解吧&#xff1a; 快速理解解题思路小建议&#xff1a; 解题方法&#xff1a; 相似题目对比分析&#xff1a; 解题分析&#xff1a; 解题思路&#xff1a; 补充说明&#xff1a; 思路优化&#xff1a; 代码实现(层序遍历倒序)&#xff1a; 题…

osg模型的平移、缩放、旋转

加载2个模型&#xff0c;其中一个向上移动28个单位&#xff1b; 加载2个模型&#xff0c;其中一个缩放0.5倍&#xff0c;向下移动22个单位&#xff1b; 加载2个模型&#xff0c;其中一个缩放0.5倍、旋转45度、向右向下移动几个单位&#xff1b; 都是用矩阵实现的&#xff1b; …

基于CEVA DSP BX2的架构分析(六)-加载和存储单元(二)

6.4 指针修改机制 LS0和LS1都包含指针修改机制。当使用间接或索引寻址模式时&#xff0c;指针的修改可以与地址生成并行执行。在间接寻址模式中&#xff0c;指针包含地址&#xff0c;而在变址寻址模式下&#xff0c;指针包含偏移量&#xff08;有关这些寻址模式的更多详细信息&…

axios get 请求 url 转码 空格转成+,导致请求失败(前端解决)

问题 GET 请求参数&#xff1a; URL-encoded 后&#xff1a; 浏览器将空格转成了&#xff0c;导致服务报错&#xff0c;返回 400。 解决 在请求拦截器中&#xff0c;对 params 进行处理。 axios.interceptors.request.use((config) > {let url config.url;if (config…