当前位置:网站首页>es6迭代协议
es6迭代协议
2022-08-05 05:13:00 【@前端攻城狮】
迭代协议
迭代协议分为两个协议:可迭代协议和迭代器协议。
可迭代协议
可迭代协议允许 JavaScript 对象定义或定制它们的迭代行为。如果一个对象(或它原型链上的对象)实现了**[Symbol.iterator]方法,称该对象满足可迭代协议,也称该对象为可迭代对象**。
[Symbol.iterator]方法返回一个无参函数,该函数返回值为一个满足迭代器协议的对象,即迭代器对象。
一个可迭代对象是如何被迭代的?
当一个对象需要被迭代的时候(比如被置入一个 for...of 循环时),首先,会不带参数调用它的 [Symbol.iterator] 方法,然后使用此方法返回的迭代器获得要迭代的值。
迭代器协议
迭代器协议定义了产生一系列值(无论是有限个还是无限个)的标准方式。一个对象必须实现了具有如下特征的next()方法,才能称其为迭代器对象:
1、next() 方法是一个无参函数,返回值为一个特殊对象。
2、返回的特殊对象拥有两个属性:done(布尔值),value。
3、done的取值:如果迭代器可以产生序列中的下一个值,则为 false;如果迭代器已将序列迭代完毕,则为 true,这种情况下,value 是可选的,如果它依然存在,即为迭代结束之后的默认返回值(undefined)。
4、value的取值:任何 JavaScript 值。
5、next() 方法必须返回一个对象,该对象应当有两个属性: done 和 value,如果返回了一个非对象值,则会抛出异常。
创造一个同时满足迭代器协议和可迭代协议的对象:
var myIterator = {
next: function() {
// ...
},
[Symbol.iterator]: function() {
return this }
}
可迭代对象
内置可迭代对象有:String、Array、TypedArray、Map 和 Set,它们的原型对象都实现了 [Symbol.iterator] 方法。
自定义可迭代对象:
var myIterable = {
};
myIterable[Symbol.iterator] = function* () {
// 生成器函数
yield 1;
yield 2;
yield 3;
};
[...myIterable]; // [1, 2, 3]
接收可迭代对象的内置API:
new Map([iterable])new WeakMap([iterable])new Set([iterable])new WeakSet([iterable])Promise.all(iterable)Promise.race(iterable)Array.from(iterable)
…
例如:
new Map([[1, 'a'], [2, 'b'], [3, 'c']]).get(2); // "b"
let myObj = {
};
new WeakMap([
[{
}, 'a'],
[myObj, 'b'],
[{
}, 'c']
]).get(myObj); // "b"
new Set([1, 2, 3]).has(3); // true
new Set('123').has('2'); // true
new WeakSet(function* () {
yield {
};
yield myObj;
yield {
};
}()).has(myObj); // true
需要可迭代对象的语法:
一些语句和表达式需要可迭代对象,比如 for...of 循环、展开语法、yield*,和解构赋值:
for(let value of ["a", "b", "c"]){
console.log(value);
}
// "a"
// "b"
// "c"
[..."abc"]; // ["a", "b", "c"]
function* gen() {
yield* ["a", "b", "c"];
}
gen().next(); // { value: "a", done: false }
[a, b, c] = new Set(["a", "b", "c"]);
a // "a"
格式不佳的可迭代对象:如果一个可迭代对象的 [Symbol.iterator] 方法不能返回迭代器对象,那么可以认为它是一个格式不佳的(Non-well-formed)可迭代对象 。
使用这样的可迭代对象很可能会导致如下的运行时(runtime)异常,或者不可预料的表现:
var nonWellFormedIterable = {
}
nonWellFormedIterable[Symbol.iterator] = () => 1
[...nonWellFormedIterable] // TypeError: [] is not a function
迭代器示例
返回简单迭代器的函数:
function makeIterator(array) {
let nextIndex = 0;
return {
next: function () {
if(nextIndex < array.length) {
return {
value: array[nextIndex++],
done: false
}
}
else {
return {
done: true
}
}
}
}
}
let it = makeIterator(['哟', '呀']);
console.log(it.next().value); // '哟'
console.log(it.next().value); // '呀'
console.log(it.next().done); // true
返回无穷迭代器的函数:
function idMaker() {
let index = 0;
return {
next: function() {
return {
value: index++,
done: false
};
}
};
}
let it = idMaker();
console.log(it.next().value); // '0'
console.log(it.next().value); // '1'
console.log(it.next().value); // '2'
// ...
使用生成器:
// 简单生成器
function* makeSimpleGenerator(array) {
let nextIndex = 0;
while(nextIndex < array.length) {
yield array[nextIndex++];
}
}
let gen = makeSimpleGenerator(['哟', '呀']);
console.log(gen.next().value); // '哟'
console.log(gen.next().value); // '呀'
console.log(gen.next().done); // true
// 无穷生成器
function* idMaker() {
let index = 0;
while (true) {
yield index++;
}
}
let gen = idMaker();
console.log(gen.next().value); // '0'
console.log(gen.next().value); // '1'
console.log(gen.next().value); // '2'
// ...
es6类中的迭代器(自定义可迭代对象):
class SimpleClass {
constructor(data) {
this.data = data
}
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.data.length) {
return {
value: this.data[index++], done: false}
} else {
return {
done: true}
}
}
}
}
}
const simple = new SimpleClass([1,2,3,4,5]);
for (const val of simple) {
console.log(val) //1 2 3 4 5
}
生成器对象到底是一个迭代器对象,还是一个可迭代对象?
结论是:生成器对象既是迭代器,也是可迭代对象。
let aGeneratorObject = function* (){
yield 1;
yield 2;
yield 3;
}();
typeof aGeneratorObject.next;
// 返回"function", 因为有一个next方法,所以这是一个迭代器
typeof aGeneratorObject[Symbol.iterator];
// 返回"function", 因为有一个@@iterator方法,所以这是一个可迭代对象
aGeneratorObject[Symbol.iterator]() === aGeneratorObject;
// 返回true, 因为@@iterator方法返回自身(即迭代器),所以这是一个格式良好的可迭代对象
[...aGeneratorObject];
// 返回[1, 2, 3]
console.log(Symbol.iterator in aGeneratorObject)
// 返回true, 因为@@iterator方法是aGeneratorObject的一个属性
边栏推荐
- number_gets the specified number of decimals
- 第二讲 Linear Model 线性模型
- What field type of MySQL database table has the largest storage length?
- The fourth back propagation back propagation
- shell函数
- 逆向理论知识4
- Pycharm中使用pip安装第三方库安装失败:“Non-zero exit code (2)“的解决方法
- Mysql5.7 二进制 部署
- Using pip to install third-party libraries in Pycharm fails to install: "Non-zero exit code (2)" solution
- pycharm中调用Matlab配置:No module named ‘matlab.engine‘; ‘matlab‘ is not a package
猜你喜欢

第5讲 使用pytorch实现线性回归

Database experiment five backup and recovery

逆向理论知识4

The difference between span tag and p

span标签和p标签的区别

多线程查询结果,添加List集合

Difference between for..in and for..of

ESP32 485 Illuminance

pycharm中调用Matlab配置:No module named ‘matlab.engine‘; ‘matlab‘ is not a package
![[cesium] 3D Tileset model is loaded and associated with the model tree](/img/03/50b7394f33118c9ca1fbf31b737b1a.png)
[cesium] 3D Tileset model is loaded and associated with the model tree
随机推荐
uva1325
A blog clears the Redis technology stack
软件设计 实验四 桥接模式实验
Opencv中,imag=cv2.cvtColor(imag,cv2.COLOR_BGR2GRAY) 报错:error:!_src.empty() in function ‘cv::cvtColor‘
判断语句_switch与case
Mesos学习
day9-字符串作业
第二讲 Linear Model 线性模型
redis复制机制
数字_获取指定位数的小数
【练一下1】糖尿病遗传风险检测挑战赛 【讯飞开放平台】
【技能】长期更新
Convert the paper official seal in the form of a photo into an electronic official seal (no need to download ps)
Judgment statement _switch and case
In Opencv, imag=cv2.cvtColor(imag,cv2.COLOR_BGR2GRAY) error: error:!_src.empty() in function 'cv::cvtColor'
Lecture 5 Using pytorch to implement linear regression
Redux
2022 Hangzhou Electric Multi-School 1st Session 01
【过一下12】整整一星期没记录
Do you use tomatoes to supervise your peers?Add my study room, come on together