4.展开语法(Spread) - JS

认识 Spread

  1. ...,展开运算符(如果算是运算符);
  2. 可迭代对象展开成参数列表(如果将很多行为看待称一个函数行为)。

基本语法

根据基本用途:

  1. 用作函数传参;
  2. 用作构造数组;
  3. 用作构造对象(浅拷贝)。

语法如下:

/* 用作函数传参:可迭代对象可以是数组、字符串、集合、生成器等等有迭代入口的对象 */
func(0个或更多其他参数, ...可迭代对象, 0个或更多其他参数)

/* 用作构造数组; */
[ 1, 2, ...[3, 4], 5, ...'67890' ]
[...[1, 2], ...[3, 4, 5]]	// 像这样的数组拼接,也可以使用 concat 方法

/* 用作构造对象(浅拷贝):也叫属性拷贝什么的 */
let objClone = { ...obj };

一个简单例子 - 数组最值

尝试使用函数 Math.max / Math.min 求一个数组的最大/最小值:

  1. 直接将数组传入,数组被当成一个数据,一个非数的数据,得到结果是 NaN
  2. 进一步,我们知道,使用函数的 apply 方法,可以将数组或类数组的元素作为参数列表进行传参;
  3. 更进一步,使用展开语法,也可以将数组展开,再作为参数传给函数。
const arr = [1, 2, 4];
Math.max(arr)					// NaN

Math.max.apply(null, arr)		// 4
Math.max(...arr)				// 4
Math.max(1, 2, 4)				// 4 等价于前两种
Math.max(...'124')				// 4 字符串也是可迭代对象

Spread 语法的应用

代替函数的 apply 方法

使用展开语法,将类数组展开成参数列表:

let args = [1, 2, 3, 4];
sum.apply(null, args)			// 10
sum(...args)					// 10
sum(...'1234')					// 10
sum(1, ...[2, 3], ...[], 4, 5)	// 15

function sum(...rest) {
	let total = 0;
	for (const elem of rest) total += +elem;
	return total;
}

构造数组

  1. 复制数组(浅拷贝);
  2. 拼接数组。
/* 1. 复制数组 */
let arr1 = [1, 2, 3];
let arr2 = [...arr1];
let arr3 = arr1.slice()

/* 2. 拼接数组 */
let a1 = [1, 2], a2 = [3, 4];
let a3 = [...a1, ...a2];
let a4 = a1.concat(a2);

构造对象

  1. 复制对象(浅拷贝);
  2. 拼接对象。
/* 1. 复制对象 */
let obj1 = { a: 1, b: 2 }, obj2 = { a: 1, c: 3 };
let o = { ...obj1 };
let oo = Object.assign(obj1);

/* 2. 拼接对象 */
let a1 = [1, 2], a2 = [3, 4];
let a3 = [...a1, ...a2];
let a4 = a1.concat(a2);

字符串的展开

  1. 将字符串展开成数组;
  2. 能够正确识别任意字节长度的 Unicode 字符。
[...'hi']				// ['h', 'i']
[...'\u4e2d\u56fd!']	// ['中', '国', '!']

/* 4个字节的 Unicode 字符,如一个火箭表情 🚀 */
'\ud83d'					// 😀
'\ud83d\ude80'				// 🚀
'\ud83d\ude80'.length		// 2
[...'\ud83d\ude80'].length	//1

生成器的展开

  1. 要展开可穷尽的生成器;
function* gen() {
	yield* [1, 2, 3]
}
let x = [...gen()];
x		// [1, 2, 3]

function* fibonacci() {
  let current = 0;
  let next = 1;
  while (true) {
    const reset = yield current;
    [current, next] = [next, next + current];
    if (reset) {
      current = 0;
      next = 1;
    }
  }
}
let xx = [...fibonacci()]	// 崩掉

展开语法 VS 剩余参数语法

  1. 都是使用 ...,含义却像正逆运算;
  2. 剩余参数语法:在函数声明时,将剩余参数收纳到最后一个参数中;
  3. 展开语法:在函数调用时,将可迭代对象的元素展开到参数列表中。
function sum(first=0, ...rest) {
	let total = first;
	for (const elem of rest) total += +elem;
	return total;
}

sum(1, 2, 3, 4)			// 10
// 第一个参数 1对应first,其他被收纳到 rest(rest=[2,3,4])
sum(...[1, 2, 3, 4])	// 10
// ...[1, 2, 3, 4] 先展开,等价于 sum(1, 2, 3, 4)
sum(...[], ...[1, 2], 3, 4)
  • 10
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值