Es6 复阅(10-1)(部分是非es6的) --数组的扩展 (扩展运算符)

1.扩展运算符

扩展运算符(spread)是三个点(…)。它好比 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

  • 扩展运算符与正常的函数参数可以结合使用,非常灵活。
	[1, 3, 4, ...[5, 6, 7, 8, 9], 7, 54, 232];
	//[ 1, 3, 4, 5, 6, 7, 8, 9, 7, 54, 232 ]
  • 用于函数调用:
	let arr = [];
	function testFn(a,...items){
		arr.push(...items);
	}
	testFn(1,2,3,4,5,6,78)
	//arr: [ 2, 3, 4, 5, 6, 78 ]

参数中 testFn(a,…items) 使用了 reset 参数,调用时 arr.push(…items) 使用了 扩展运算符

有了扩展运算符,这里push 的时候我们就不用写循环

  • 如果扩展运算符后面是一个空数组,则不产生任何效果
	[...[],1];// [1]
  • 扩展运算符后面还可以放置表达式
	let x = 0;
	const arr = [
	  ...(x > 0 ? ['a'] : []),
	  'b',
	];

表达式得出的结果必须是数组,不然就会报错 (这样说对不对噢)

:(…[items]) 这种在圆括号中使用扩展运算符只能是在函数调用的时候,否则就会进行报错

	Unexpected number
  • 替代apply方法 (仅仅只是替代它传递数组做参数的这个功能

先康康apply 方法:

	1.Function.apply(obj,args)方法能接收两个参数
	2.obj:Function 中的this 绑定为 obj
	3.args:这个是数组,它将作为参数传给Function(args–>arguments)

试试:

	let obj = {
	    name: 'heihei'
	}
	function Factory(name) {
	    console.log(this);// obj
	    console.log(arguments);//[Arguments] { '0': 1, '1': 2, '2': 3, '3': 4, '4': 5 }
	    this.name = name;
	}
	Factory.apply(obj, [1, 2, 3, 4, 5])

这里有个问题: apply() 的第二个参数必须是数组,否则就会报错:

CreateListFromArrayLike called on non-object

对比:

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

这样一看,果然是更加简便了,也更容易理解

扩展运算符的应用

  1. 复制数组
	let arr = [1, 2, 3, 4, 5, 6];
	
	let arrCopy = [...arr];
	
	arrCopy[1] = 999;
	
	console.log(arr); // [1, 2, 3, 4, 5, 6]
	console.log(arrCopy);//[ 1, 999, 3, 4, 5, 6 ];

当然,也可以复制对象

	let obj = { firstName: 'xm', lastName: 'z' };
	let newObj = {...obj };
	newObj.firstName = 'newName';
	console.log(newObj);//{ firstName: 'newName', lastName: 'z' }
	console.log(obj);//{ firstName: 'xm', lastName: 'z' }

注:仅仅适合一层的数组,对象 ,如果数组或者对象内部又引用了其他的对象或者数组,那么对于这一层来说就仍然是浅拷贝,深浅拷贝专场 (这里有链接)

  1. 合并数组
	//使用concat 
	let arr = [1, 2, 3, 4];
	let arr2 = [5, 6, 7, 8];
	arr2 = arr2.concat(arr);// [5,6,7,8,1,2,3,4]
	
	//使用扩展运算符
	let arr3 = [...arr,...arr2];//[ 1, 2, 3, 4, 5, 6, 7, 8, 1, 2, 3, 4 ];

能少敲好几个单词 [doge]

  1. 结合结构赋值
	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   // []
  1. 将字符串转为数组,这个做法是不是十分熟悉
	let str = 'helloWorld';
	let arr = str.split('');//[ 'h', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd' ]

使用扩展运算符:

	let arr = [...str];//[ 'h', 'e', 'l', 'l', 'o', 'W', 'o', 'r', 'l', 'd' ]

如果仅仅是将字符串转换成数组,则两种方法都适用,如果是需要以特定的字符对字符串进行分割,则 spllit() 适用

还有另一个好处:能够正确识别四个字节的 Unicode 字符

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

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

  1. 任何定义了遍历器(Iterator)接口的对象(参阅 Iterator 一章),都可以用扩展运算符转为真正的数组。
	Number.prototype[Symbol.iterator] = function*() {
	  let i = 0;
	  let num = this.valueOf();
	  while (i < num) {
	    yield i++;
	  }
	}
	
	console.log([...5]) // [0, 1, 2, 3, 4]

Map

	let map = new Map([
	  [1, 'one'],
	  [2, 'two'],
	  [3, 'three'],
	]);//Map { 1 => 'one', 2 => 'two', 3 => 'three' }
	
	let arr = [...map.keys()]; // [1, 2, 3]
	//keys方法可以返回一个Map对象的键的遍历器对象。

JavaScript — Map集合结构详解

Generator 函数 [Generator 函数详解]

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

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

发布了50 篇原创文章 · 获赞 4 · 访问量 1259

猜你喜欢

转载自blog.csdn.net/weixin_43910427/article/details/105432096