Array
Array.from
- Array 构造函数还有两个 ES6 新增的用于创建数组的静态方法:from()和 of()。from()用于将
类数组结构转换为数组实例,而 of()用于将一组参数转换为数组实例。
Array.from()的第一个参数是一个类数组对象,即任何可迭代的结构,或者有一个 length 属性
和可索引元素的结构。这种方式可用于很多场合:
// 字符串会被拆分为单字符数组
console.log(Array.from("Matt")); // ["M", "a", "t", "t"]
// 可以使用 from()将集合和映射转换为一个新数组
const m = new Map().set(1, 2)
.set(3, 4);
const s = new Set().add(1)
.add(2)
.add(3)
.add(4);
console.log(Array.from(m)); // [[1, 2], [3, 4]]
console.log(Array.from(s)); // [1, 2, 3, 4]
// Array.from()对现有数组执行浅复制
const a1 = [1, 2, 3, 4];
const a2 = Array.from(a1);
console.log(a1); // [1, 2, 3, 4]
alert(a1 === a2); // false
// 可以使用任何可迭代对象
const iter = {
*[Symbol.iterator]() {
yield 1;
yield 2;
yield 3;
yield 4;
}
};
console.log(Array.from(iter)); // [1, 2, 3, 4]
// arguments 对象可以被轻松地转换为数组
function getArgsArray() {
return Array.from(arguments);
}
console.log(getArgsArray(1, 2, 3, 4)); // [1, 2, 3, 4]
// from()也能转换带有必要属性的自定义对象
const arrayLikeObject = {
0: 1,
1: 2,
2: 3,
3: 4,
length: 4
};
console.log(Array.from(arrayLikeObject)); // [1, 2, 3, 4]
Array.from()还接收第二个可选的映射函数参数。这个函数可以直接增强新数组的值,而无须像
调用 Array.from().map()那样先创建一个中间数组。还可以接收第三个可选参数,用于指定映射函
数中 this 的值。但这个重写的 this 值在箭头函数中不适用。
const a1 = [1, 2, 3, 4];
const a2 = Array.from(a1, x => x**2);
const a3 = Array.from(a1, function(x) {return x**this.exponent}, {exponent: 2});
console.log(a2); // [1, 4, 9, 16]
console.log(a3); // [1, 4, 9, 16]
Array.of()可以把一组参数转换为数组。这个方法用于替代在 ES6之前常用的 Array.prototype.
slice.call(arguments),一种异常笨拙的将 arguments 对象转换为数组的写法:
console.log(Array.of(1, 2, 3, 4)); // [1, 2, 3, 4]
console.log(Array.of(undefined)); // [undefined]
迭代方法
ECMAScript 为数组定义了 5 个迭代方法。每个方法接收两个参数:以每一项为参数运行的函数,
以及可选的作为函数运行上下文的作用域对象(影响函数中 this 的值)。传给每个方法的函数接收 3
个参数:数组元素、元素索引和数组本身。因具体方法而异,这个函数的执行结果可能会也可能不会影
响方法的返回值。数组的 5 个迭代方法如下。
- every():对数组每一项都运行传入的函数,如果对每一项函数都返回 true,则这个方法返回 true。
- filter():对数组每一项都运行传入的函数,函数返回 true 的项会组成数组之后返回。
- forEach():对数组每一项都运行传入的函数,没有返回值。
- map():对数组每一项都运行传入的函数,返回由每次函数调用的结果构成的数组。
- some():对数组每一项都运行传入的函数,如果有一项函数返回 true,则这个方法返回 true。
这些方法都不改变调用它们的数组。
在这些方法中,every()和 some()是最相似的,都是从数组中搜索符合某个条件的元素。对 every()
来说,传入的函数必须对每一项都返回 true,它才会返回 true;否则,它就返回 false。而对 some()
来说,只要有一项让传入的函数返回 true,它就会返回 true。下面是一个例子:
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let everyResult = numbers.every((item, index, array) => item > 2);
alert(everyResult); // false
let someResult = numbers.some((item, index, array) => item > 2);
alert(someResult); // true
以上代码调用了 every()和 some(),传入的函数都是在给定项大于 2 时返回 true。every()返 回 false 是因为并不是每一项都能达到要求。而 some()返回 true 是因为至少有一项满足条件。
下面再看一看 filter()方法。这个方法基于给定的函数来决定某一项是否应该包含在它返回的数
组中。比如,要返回一个所有数值都大于 2 的数组,可以使用如下代码:
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let filterResult = numbers.filter((item, index, array) => item > 2);
alert(filterResult); // 3,4,5,4,3
这里,调用 filter()返回的数组包含 3、4、5、4、3,因为只有对这些项传入的函数才返回 true。
这个方法非常适合从数组中筛选满足给定条件的元素。
接下来 map()方法也会返回一个数组。这个数组的每一项都是对原始数组中同样位置的元素运行传
入函数而返回的结果。例如,可以将一个数组中的每一项都乘以 2,并返回包含所有结果的数组,如下
所示:
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
let mapResult = numbers.map((item, index, array) => item * 2);
alert(mapResult); // 2,4,6,8,10,8,6,4,2
以上代码返回了一个数组,包含原始数组中每个值乘以 2 的结果。这个方法非常适合创建一个与原
始数组元素一一对应的新数组。
最后,再来看一看 forEach()方法。这个方法只会对每一项运行传入的函数,没有返回值。本质
上,forEach()方法相当于使用 for 循环遍历数组。比如:
let numbers = [1, 2, 3, 4, 5, 4, 3, 2, 1];
numbers.forEach((item, index, array) => {
// 执行某些操作
});
数组的这些迭代方法通过执行不同操作方便了对数组的处理。