Iterable object (可迭代对象) 可迭代(Iterable) 对象是数组的泛化。这个概念是说任何对象都可以被定制为可在 for..of
循环中使用的对象。
数组是可迭代的。但不仅仅是数组。很多其他内建对象也都是可迭代的。例如字符串也是可迭代的。
Symbol.itetator 我们有一个对象,并不是数组,但是看上去很适合使用 for…in 循环。
比如一个 range 对象,代表一个数字区别。
let range = {
from: 1,
to: 5
};
// 我们希望 for..of 这样运行:
// for(let num of range) ... num=1,2,3,4,5
【5-JS-数据类型-Iterable object (可迭代对象)】迭代器对象和与其进行迭代的对象是分开的。
从技术上说,我们可以将它们合并,并使用
range
自身作为迭代器来简化代码。就像这样:
let range = {
from: 1,
to: 5,[Symbol.iterator]() {
this.current = this.from;
return this;
},next() {
if (this.current <= this.to) {
return { done: false, value: this.current++ };
} else {
return { done: true };
}
}
};
for (let num of range) {
alert(num);
// 1, 然后是 2, 3, 4, 5
}
字符串是可迭代的 数组和字符串是使用最广泛的内建可迭代对象。
对于一个字符串,
for..of
遍历它的每个字符:for (let char of "test") {
// 触发 4 次,每个字符一次
alert( char );
// t, then e, then s, then t
}
显式调用迭代器 为了更深层地了解底层知识,让我们来看看如何显式地使用迭代器。
我们将会采用与
for..of
完全相同的方式遍历字符串,但使用的是直接调用。这段代码创建了一个字符串迭代器,并“手动”从中获取值。let str = "Hello";
// 和 for..of 做相同的事
// for (let char of str) alert(char);
let iterator = str[Symbol.iterator]();
while (true) {
let result = iterator.next();
if (result.done) break;
alert(result.value);
// 一个接一个地输出字符
}
可迭代和类数组
- Iterable 如上所述,是实现了
Symbol.iterator
方法的对象。 - Array-like 是有索引和
length
属性的对象,所以它们看起来很像数组。
let arrayLike = { // 有索引和 length 属性 => 类数组对象
0: "Hello",
1: "World",
length: 2
};
// Error (no Symbol.iterator)
for (let item of arrayLike) {}
可迭代对象和类数组对象通常都 不是数组,它们没有
push
和 pop
等方法。如果我们有一个这样的对象,并想像数组那样操作它,那就非常不方便。Array.from 接受一个可迭代或类数组的值,并从中获取一个真正的数组。然后就可以对其调用数组方法。
举例
let arrayLike = {
0: "Hello",
1: "World",
length: 2
};
let arr = Array.from(arrayLike);
// (*)
alert(arr.pop());
// World(pop 方法有效)
如果是可迭代对象,也是同样:
// 假设 range 来自上文的例子中
let arr = Array.from(range);
alert(arr);
// 1,2,3,4,5 (数组的 toString 转化方法生效)
举例:
// 假设 range 来自上文例子中// 求每个数的平方
let arr = Array.from(range, num => num * num);
alert(arr);
// 1,4,9,16,25
将一个字符串转换为单个字符的数组
let str = '';
// 将 str 拆分为字符数组
let chars = Array.from(str);
alert(chars[0]);
//
alert(chars[1]);
//
alert(chars.length);
// 2
技术上讲,它和下面一段代码做的是相同的事情
let str = '';
let chars = [];
// Array.from 内部执行相同的循环
for (let char of str) {
chars.push(char);
}alert(chars);
我们甚至可以基于
Array.from
创建代理感知(surrogate-aware)的slice
方法(译注:也就是能够处理 UTF-16 扩展字符的 slice
方法):function slice(str, start, end) {
return Array.from(str).slice(start, end).join('');
}let str = '';
alert( slice(str, 1, 3) );
// // 原生方法不支持识别代理对(译注:UTF-16 扩展字符)
alert( str.slice(1, 3) );
// 乱码(两个不同 UTF-16 扩展字符碎片拼接的结果)
推荐阅读
- vue|vue个人在线简历
- vue3|While resolving: aidr-web-service-web@1.0.0 vue3安装依赖报错
- vue|vue3组件封装之搜索组件的封装
- vue|Vue3传送组件Teleport
- js|JS深浅拷贝
- 零基础学JavaScript|三,零基础学习JavaScript----词法结构
- JS|react-to-print 打印
- node|node和express实现mySql模糊搜索
- vue|vue中使用videojs