概览
ES6引进了一些新的数组办法。
扩大运算符(Spread)+残余操作符(Rest)
含意: 扩大运算符(spread)是三个点...
,它如同rest参数的逆运算,将一个数组转为用逗号分隔的参数序列。
- 残余操作符提取数组,用于残余参数和构造。
- 扩大操作符将数组元素转换成函数调用的参数或者数组字面量的元素。
console.log(...[1, 2, 3]); // 1 2 3console.log(1, ...[2, 3, 4], 5); //1 2 3 4 5
Rest(函数参数) 和 Spread(数组运算符) 次要是利用 ... 运算符,实现值的聚合和合成。
// 1.rest失去的是一个真正的数组,而不是一个伪数组。const getOptions = function(...args){ console.log(args.join());}const arr = [123];getOptions(...arr); // 123// 2.rest能够搭配箭头函数应用,达到获得所有参数的目标。const getOption = (...args)=>{ console.log(args);}let arrs = [1,2,3];getOption(...arrs); // [1,2,3]// 3.spread能够用于解构时,聚合所得的值。const opt1 = 'one';const opt2 = ['two','three','four'];console.log([opt1,...opt2]); // ["one", "two", "three", "four"]//4.spread能够用于数组定义。const opts = ["one", "two", "three", "four"];const config = ['other', ...opts]
该运算符次要用于函数的调用。
function push(array, ...items){ array.push(...items);}function add(x, y){ return x + y;}const numbers = [4, 38];console.log(add(...numbers));; // 42
从下面的代码能够看出,该运算符能够将一个数组变成为参数序列。
function f(v, w, x, y, z){ console.log([v, w, x, y, z]);}const args = [0, 1];f(-1, ...args, 2, ...[3]) // [-1, 0, 1, 2, 3]
扩大运算符前面搁置表达式。
const arr = [ ...(x > 0 ? ['a'] : []), 'b',]
如果扩大运算符前面是一个空数组,则不产生任何成果。
console.log([...[], 1]); // [1]
扩大运算符利用
代替数组的apply办法:
// 因为扩大运算符能够开展数组,所以不须要应用apply办法将数组转为函数的参数。// ES5 写法function f(x,y,z){ console.log(x,y,z);}const args = [0,1,2];f.apply(null,args) // 0 1 2// ES6 写法function f1(x,y,z){ console.log(x,y,z);}f1(...args) // 0 1 2// ES5 写法console.log(Math.max.apply(null,[14,3,77])); //77// ES6 写法console.log(Math.max(...[14,3,77])); //77//等同于console.log(Math.max(14,3,77)); //77// ES5 写法const arr1 = [0,1,2];const arr2 = [3,4,5];Array.prototype.push.apply(arr1,arr2);console.log(arr1); // [0, 1, 2, 3, 4, 5]// ES6 写法const arr11 = [0,1,2];const arr22 = [3,4,5];arr11.push(...arr22);console.log(arr11); // [0, 1, 2, 3, 4, 5]// ES5 写法console.log(new (Date.bind.apply(Date, [null , 2015, 1, 1]))); // Sun Feb 01 2015 00:00:00 GMT+0800 (中国规范工夫)// ES6 写法console.log(new Date(...[2015, 1, 1])); // Sun Feb 01 2015 00:00:00 GMT+0800 (中国规范工夫)
合并数组:
// ES5 写法const more = [2,2,2];console.log([1,2].concat(more)); // [1,2,2,2,2]// ES6 写法console.log([1,2,...more]); // [1,2,2,2,2]// ES5 写法const arr1 = ['a','b'];const arr2 = ['c','d'];const arr3 = ['e','f'];const arr = arr1.concat(arr2,arr3)console.log(arr); // ["a", "b", "c", "d", "e", "f"]// ES6 写法console.log([...arr1,...arr2,...arr3]); // ["a", "b", "c", "d", "e", "f"]console.log([1, ...[2,3], 4]); // [1,2,3,4]
与解构赋值联合:
// ES5 写法const list = [1,2];const a = list[0];const rest = list.slice(1);console.log(a, rest); // 1 [2]// ES6 写法[a1, ...rest1] = list;console.log(a1,rest1); // 1 [2] // 其余例子const [first,...res] = [1,2,3,4,5];console.log(first,res); // 1 [2,3,4,5]const [first1,...res1] = [];console.log(first1,res1); //undefined []const [first2,...res2] = ['foo'];console.log(first2,res2); // 'foo' []const [...butLast, last] = [1,2,3,4,5] // 报错 Rest element must be last elementconst [first3,...middle, last] = [1,2,3,4,5] // 报错 Rest element must be last element
函数返回值:
JavaScript的函数只能返回一个值,如果须要返回多个值,只能返回数组或对象。扩大运算符提供了解决这个问题的一种变通方法。
字符串:
// 将字符串转为真正的数组console.log([...'hello']); // ['h','e','l','l','o']// 正确辨认32位的Unicodeconsole.log([...'x\uD83D\uDE80y'].length); // 3
实现了Iterator接口的对象:
任何Iterator接口的对象,都能够用扩大运算符转为真正的数组。
对于那些没有部署Iterator接口的相似数组的对象,扩大运算符就无奈将其转为真正的数组。
const arrayLike = { '0': 'a', '1': 'b', '2': 'c', length: 3}// ES5 转为数组 const arrNew1 = [].slice.call(arrayLike);console.log(arrNew1); // ['a','b','c']// ES6 转为数组const arrNew2 = Array.from(arrayLike); // ['a', 'b', 'c']console.log(arrNew2); // ['a', 'b', 'c']// Uncaught TypeError: arrayLike is not iterable.const arrNew3 = [...arrayLike];
Map和Set构造、Generator函数:
// Map构造let map = new Map([ [1,'one'], [2,'two'], [3,'three'],])let arr1 = [...map.keys()];let arr2 = [...map.values()];console.log(arr1,arr2); // [1, 2, 3] ["one", "two", "three"]// Set构造let set = new Set([11,-1,6]);let arrNew = [...set];console.log(arrNew); // [11,-1,6]// Generator函数const go = function*(){ yield 1; yield 2; yield 3;}console.log([...go()]); // [1,2,3]const obj = { * [Symbol.iterator](){ yield 'a'; yield 'b'; yield 'c'; }}console.log([...obj]); // ['a','b','c']// 对于没有Iterator接口的对象,应用扩大运算符会报错const obj1 = { a:1, b:2,}console.log([...obj1]); // Uncaught TypeError: obj1 is not iterable
数组类办法Array.from()
Array.from()
办法用于将两类对象转为真正的数组:相似数组的对象(array-like object)和可遍历(iterator)对象(包含ES6新增的数据结构Set和Map)。
相似数组对象转为数组:
let arrayLike = { '0':'a', '1':'b', '2':'c', length:3}// ES5 写法let arrNew1 = [].slice.call(arrayLike);console.log(arrNew1); // ['a','b','c']// ES6 写法let arrNew2 = Array.from(arrayLike);console.log(arrNew2); // ['a','b','c']
NodeList对象转为数组:
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title></head><body> <p>1</p> <p>2</p> <p>3</p> <script> const ps = document.querySelectorAll('p'); Array.from(ps).forEach(function(p){ console.log(p); }) Array.from(ps).map(function(val){ console.log(val); }) Array.from(ps, x =>console.log(x)) </script></body></html>
arguments对象转为数组:
function foo(x = 0,y = 12) { let args = Array.from(arguments) console.log(args);}foo(); // []foo(1); // [1]foo(1,2); // [1,2]
字符串(Iterator接口)转为数组:
console.log(Array.from('hello')); // ["h", "e", "l", "l", "o"]
Set构造(Iterator接口)转为数组:
let nameSet = new Set(['a','b']);console.log(Array.from(nameSet)); // ["a", "b"]
操作数组:
console.log(Array.from([1,2,3])); // [1,2,3]
相似数组的对象,非凡状况:
console.log(Array.from({length:3})); // [undefined,undefined,undefined]console.log(Array.from({length:2},()=>'jack')); // ["jack", "jack"]
转数组兼容性思考:
const toArray = (()=> Array.from?Array.from:obj=>[].slice.call(obj))();
将数组中布尔值为false的成员转为0:
console.log(Array.from([1,,2,,3],(n)=>n||0)); // [1, 0, 2, 0, 3]
返回各种数据的类型:
function typesOf(){ return Array.from(arguments,value=>typeof value)}console.log(typesOf(null,[],NaN)); // ["object", "object", "number"]
防止将大于\uFFFF的Unicode字符算作两个字符的bug:
function countSymbols(string){ return Array.from(string).length}
数组类办法Array.of()
将一组值转换为数组,补救数组构造函数Array的有余。Array.of()
总是返回参数值组成的数组,如果没有参数,就返回一个空数组。
console.log(Array.of()); // []console.log(Array.of(undefined)); //[undefined]console.log(Array.of(null)); // [null]console.log(Array.of(1)); // [1]console.log(Array.of(1,2)); // [1,2]console.log(Array.of(3,4,7)); // [3,4,7]
Array 子类的构造函数会继承所有的 Array 类的办法,包含 of() 办法
class MyArray extends Array {}console.log(MyArray.of(3, 11, 8) instanceof MyArray); // trueconsole.log(MyArray.of(3).length === 1); // true
数组原型办法copyWithin()
会在以后数组外部制订地位的成员复制到其余地位(会笼罩原有成员),会返回以后数组。Array.prototype.copyWithin(target,start=0,end=this.length)
- target(必选):从以后地位开始替换数据。
- start(可选):从该地位开始读取数据,默认0.如果为负值,示意倒数。
- end(可选):到该地位前进行读取数据,默认等于数组长度。如果为负值,示意倒数。
// 将3号位到最初一位复制0号位开始往后排let arr1 = [1,2,3,4,5]arr1.copyWithin(0,3);console.log(arr1); // [4, 5, 3, 4, 5]// 将3号位复制到0号位let arr2 = [1,2,3,4,5]arr2.copyWithin(0,3,4);console.log(arr2); // [4, 2, 3, 4, 5]// -2相当于3号位,-1相当于4号位let arr3 = [1,2,3,4,5];arr3.copyWithin(0,-2,-1);console.log(arr3); // [4, 2,3 , 4, 5]// 将3号位复制到0号位let arr4 = [].copyWithin.call({length:5,3:1},0,3);console.log(arr4); // {0: 1, 3: 1, length: 5}// 将2号位到数组完结,复制到0号位let arr5 = new Int32Array([1,2,3,4,5])arr5.copyWithin(0,2)console.log(arr5); // Int32Array(5) [3, 4, 5, 4, 5]// 对于没有部署TypedArray的copyWithin办法的平台// 须要采纳上面的写法let arr6 = [].copyWithin.call(new Int32Array([1,2,3,4,5]),0,3,4);console.log(arr6); // Int32Array(5) [4, 2, 3, 4, 5]
数组原型办法find()
和findIndex()
find()
办法用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有的数组成员顺次执行该回调函数,直到找出第一个返回值为true的成员,而后返回该成员,如果没有符合条件的成员,则返回undefined。
findIndex
办法与find()
办法十分相似,返回第一个符合条件的数组成员的地位,如果所有成员都不符合条件,则返回-1.
let num = [1,4,-5,10].find(n=>n < 0)console.log(num); // -5let num1 = [1,4,-5,10].find(n=>n > 11)console.log(num1); // undefinedlet num2 = [1,4,-5,10].findIndex(n=>n < 0)console.log(num2); // -5let num3 = [1,4,-5,10].findIndex(n=>n > 11)console.log(num3); // -1
承受3个参数,顺次为以后的值,以后的地位和原数组:
// find返回valuelet num4 = [1,5,10,15].find(function(value,index,arr){ return value > 9;})console.log(num4); // 10//findIndex返回indexlet num5 = [1,5,10,15].findIndex(function(value,index,arr){ return value > 9;})console.log(num5); // 2
将数组的空缺作为undefined
解决:
let num6 = ['a',,'c'].find(x=>x===undefined)console.log(num6); // undefinedlet num7 = ['a',,'c'].findIndex(x=>x===undefined)console.log(num7); // 1
通过findIndex
办法寻找NaN
:indexOf()
一个家喻户晓的局限在于它无奈寻找NaN
.
console.log([NaN].indexOf(NaN)); // -1console.log([NaN].findIndex(y=>Object.is(NaN,y))); // 0// 也能够创立辅助函数`elemIs()`function elemIs(x){ return Object.is.bind(Object, x)}console.log([NaN].findIndex(elemIs(NaN))); // 0
数组原型办法fill()
fill(value,start,end)
用给定的值填充数组:
console.log(['a','b','c'].fill(7)); // [7, 7, 7]
数组的空缺不会被非凡解决:
console.log(['a',,'c'].fill(7)); // [7, 7, 7]console.log(new Array(3).fill(7)); // [7, 7, 7]
限定填充范畴:
console.log(['a','b','c'].fill(7,1,2)); // ["a", 7, "c"]
数组原型办法keys()
、values()
和entries()
——用于遍历数组;
——都返回遍历器对象;
——可用for...of
遍历;keys()
是对键名的遍历、values()
是对键值的遍历、entries()
是对键值对的遍历。
// `Array.from()` 把迭代器中的内容放入数组console.log(Array.from(['a','b'].keys())); // [0, 1]console.log(Array.from(['a','b'].values())); // ['a', 'b']console.log(Array.from(['a','b'].entries())); // [[0, 'a'], [1, 'b']]// 开展操作符(...)将迭代器转换成数组console.log(...['a','b'].keys()); // 0 1console.log(...['a','b'].values()); // 'a' 'b'console.log(...['a','b'].entries()); // [0, 'a'] [1, 'b']// `for..of`遍历for(let index of ['a','b'].keys()){ console.log(index); }// 0 // 1for(let elem of ['a','b'].values()){ console.log(elem); }// 'a' // 'b'for(let [index, elem] of ['a','b'].entries()){ console.log(index, elem); }// 0 "a"// 1 "b"
数组原型办法includes()
includes()
办法判断某个数组是否蕴含给定的值,返回true
或者false
。
console.log([1,2,3].includes(2)); // trueconsole.log([1,2,3].includes(4)); // falseconsole.log([1,2,NaN].includes(NaN)); // true// 第二个参数示意搜寻的起始地位,默认为0。如果为正数,则示意倒数的地位,如果这时大于数组的长度则会重置为从0开始console.log([1,2,3].includes(2,-4)); // trueconsole.log([1,2,3].includes(2,-3)); // trueconsole.log([1,2,3].includes(2,-2)); // trueconsole.log([1,2,3].includes(2,-1)); // falseconsole.log([1,2,3].includes(2,0)); // trueconsole.log([1,2,3].includes(2,1)); // trueconsole.log([1,2,3].includes(2,2)); // falseconsole.log([1,2,3].includes(2,3)); // falseconsole.log([1,2,3].includes(2,4)); // false
es6数组