Array.from
Array.from
方法主要用于将Array-Like Obj
(包括DOM对象document.querySeletorAll(...)
)和iterable
对象转化为数组。和下面说的spread
操作符相比,它可以直接将Array-Like obj
进行转化,而不需要这个类数组对象是iterable
的。
function add() {
let arr = [].slice.apply(arguments);
}
function add() {
let arr = Array.from(arguments);
}
--------
//通过这个方法,将`Array-Like Obj`直接转化为了Array.因此可以使用Array提供的方法
var lis = Array.from(document.querySelectorAll('li'));
lis.forEach(function(dom, index) {
// do something
});
此外,Array.from
还接收第二个参数,和Array.prototype.map
方法类似.
function foo() {
let args = Array.from(arguments, item => item + 1);
console.log(args);
}
foo(1, 2, 3); // 2 3 4
可以利用Array.from
来返回字符串的长度,因为在js
里面,大于uFFFF的Unicode
字符长度是算为2个的。
//这里是因为String类型的数据是iterable的,所以可以被Array.from转化为数组
function countLen(str) {
return Array.from(str).length;
}
...args (rest参数)
rest
参数主要是在定义函数的时候,用以获取函数多余的函数,这样在函数内部即可不使用arguments
对象.因为rest
参数是一个数组,因此可以直接利用Array
提供的相应的API。
比如一个求和的函数:
以前的写法:
function add() {
[].reduce.call(arguments, function(x, y) {
return x + y;
});
}
es6:
function add(...args) {
args.reduce((x, y) => x + y);
}
还可以使用rest
参数搭配解构赋值
使用:
function foo(...args) {
let [x = 0, y = 2] = args;
//....
}
在使用箭头函数的时候:
function foo(...args1) {
var obj = {
add: () => {
console.log(arguments);
}
}
obj.add(1, 2, 3);
}
foo(4, 5, 6); //最后输出 [4, 5, 6]
这里因为箭头函数没有自身的this
,它内部的this
事实上是由所在的作用域提供的。因此arguments
对象也是所在作用域提供的。所以会输出[4, 5, 6]
。
这里如果要正确获取obj.add(1, 2, 3)
提供的参数,可以使用rest
参数:
function foo(...args1) {
var obj = {
add: (...args2) => {
console.log(args2);
}
}
obj.add(1, 2, 3);
}
foo(4, 5, 6); //最后输出 [1, 2, 3]
spread操作符
spread
操作符用以将一个iterable
(部署了[Symbol.Iterator]接口)的value
转化为用逗号分隔的参数序列。
哪些数据结构部署了[Symbol.Iterator]
的接口呢:
Array
Maps
Sets
部署了
[Symbol.Iterator]
接口的Array-like obj
(arguments)Dom data Structures
String
对象字面量:
var obj = {
name: 'xl',
age: 20
}
console.log(...obj);
是没有部署[Symbol.Iterator]
接口的,因此使用spread
操作符时会报错:
Uncaught TypeError: (var)[Symbol.iterator] is not a function(…)
同时,普通的Array-like
的Obj
:
var obj = {
0: 'x',
1: 'l',
length: 2
}
同样使用spread
操作符时会报错。如果将这个Array-like
的Obj
转化为Array
,则需要手动在这个obj
上配置[Symbol.iterator]
接口:
var obj = {
*[Symbol.iterator]() {
yield 'x';
yield 'l'
}
}
console.log(...obj); // x l
或者换用其他的API:
方式1: let arr1 = Array.from(obj);
方式2: let arr1 = [].slice.apply(obj);
像之前计算一组数当中最大的数:
Math.max.apply(null, [1, 2, 3]);
--->>> Math.max(...[1, 2, 3]); // 3
此外,spread
操作符还能将部署了[Symbol.Iterator]
接口的类数组对象转为用逗号分隔的参数序列:
var li = document.querySeletorAll('li');
[...li]; //转化为数组后就可以利用数组提供的API进行其他的操作
Symbol.Iterator
上面多次提到了iterable
或者是部署了[Symbol.iterable]
方法的value
,事实上它们说的都是同一个意思,一个话去概括的话就是: iterable
的数据结构提供了统一的接口供外部去获取自身的元素。它所提供的这个接口方法名称就是[Symbol.iterator]
.
上文已经提到了哪些数据结构部署了[Symbol.Iterator]
的接口。
哪些方法会调用[Symbol.Iterator]
接口呢:
解构赋值
let [a, b] = [1, 2];
for...of
循环
for(let value of [1, 2]) {
}
spread
操作符
[...document.querySelectorAll('li')]
Promise.all()/Promise.race()
Promise.all(iterableOverPromises).then(···);
Promise.race(iterableOverPromises).then(···);
yield*
yield* anIterable
关于iterable
和iterator
单独用一篇文章来写吧。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。