乐趣区

关于javascript:ES6数组扩展运算符RestSpread类方法原型方法

概览

ES6 引进了一些新的数组办法。

扩大运算符(Spread)+ 残余操作符(Rest)

含意:扩大运算符(spread)是三个点..., 它如同 rest 参数的逆运算,将一个数组转为用逗号分隔的参数序列。

  • 残余操作符提取数组,用于残余参数和构造。
  • 扩大操作符将数组元素转换成函数调用的参数或者数组字面量的元素。
console.log(...[1, 2, 3]); // 1 2 3
console.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 element
const [first3,...middle, last] = [1,2,3,4,5] // 报错 Rest element must be last element

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

字符串:

// 将字符串转为真正的数组
console.log([...'hello']); // ['h','e','l','l','o']
// 正确辨认 32 位的 Unicode
console.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); // true
console.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); // -5

let num1 = [1,4,-5,10].find(n=>n > 11)
console.log(num1); // undefined

let num2 = [1,4,-5,10].findIndex(n=>n < 0)
console.log(num2); // -5

let num3 = [1,4,-5,10].findIndex(n=>n > 11)
console.log(num3); // -1

承受 3 个参数,顺次为以后的值,以后的地位和原数组:

// find 返回 value
let num4 = [1,5,10,15].find(function(value,index,arr){return value > 9;})
console.log(num4); // 10

//findIndex 返回 index
let 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); // undefined

let num7 = ['a',,'c'].findIndex(x=>x===undefined)
console.log(num7); // 1

通过 findIndex 办法寻找 NaN:
indexOf() 一个家喻户晓的局限在于它无奈寻找NaN.

console.log([NaN].indexOf(NaN)); // -1
console.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 1
console.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 
// 1
for(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)); // true
console.log([1,2,3].includes(4)); // false
console.log([1,2,NaN].includes(NaN)); // true

// 第二个参数示意搜寻的起始地位,默认为 0。如果为正数,则示意倒数的地位,如果这时大于数组的长度则会重置为从 0 开始
console.log([1,2,3].includes(2,-4)); // true
console.log([1,2,3].includes(2,-3)); // true
console.log([1,2,3].includes(2,-2)); // true
console.log([1,2,3].includes(2,-1)); // false
console.log([1,2,3].includes(2,0)); // true
console.log([1,2,3].includes(2,1)); // true
console.log([1,2,3].includes(2,2)); // false
console.log([1,2,3].includes(2,3)); // false
console.log([1,2,3].includes(2,4)); // false

es6 数组

退出移动版