Interator和Generator
Posted 还是不会呀
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Interator和Generator相关的知识,希望对你有一定的参考价值。
Iterator和Generator
Iterator
认识迭代器
迭代器
:帮助遍历某个数据结构的对象。一个对象需要成为
迭代器
需要满足迭代器协议
。迭代器协议
定义了一个产生一系列对象的标准方式,在JS中 这个标准就是next
方法。
next
方法是一个可以传入零个或者一个参数的函数,这个函数返回一个对象,这个对象包括:
- done属性:当还没有遍历完成时done的值是 false,当遍历完成时这个值时 true。
- value属性:当前位置上的值,遍历完时对应的值是undefined
迭代器代码
为一个数组写一个迭代器
const names = ["abc", "cba", "nba"];
let index = 0;
const nameIterator = {
next: function () {
if (index < names.length) {
return { done: false, value: names[index++] };
} else {
return { done: true, value: undefined };
}
},
};
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
console.log(nameIterator.next());
// { done: false, value: 'abc' }
// { done: false, value: 'cba' }
// { done: false, value: 'nba' }
// { done: true, value: undefined }
创建数组迭代器的工厂函数
function createArrayIterator(arr) {
let index = 0;
return {
next: function () {
if (index < arr.length) {
return { done: false, value: arr[index++] };
} else {
return { done: true, value: undefined };
}
},
};
}
const nums = [1, 2, 3];
const numsIterator = createArrayIterator(nums);
console.log(numsIterator.next());
console.log(numsIterator.next());
console.log(numsIterator.next());
console.log(numsIterator.next());
认识可迭代对象
可迭代对象
也是一个对象。但是可迭代对象≠迭代器
。一个对象符合
可迭代协议
就可以是一个可迭代对象。可迭代对象
需要有@@ iterator
方法,在JS代码中表现为Symbol.iterator
访问该属性。
Symbol.iterator
是一个函数,这个函数的返回值是一个迭代器
可迭代对象代码
这种方式和迭代器代码相比,代码之间的关联度更加紧密了
const info = {
name: ["abc", "cba", "nba"],
[Symbol.iterator]: function () {
let index = 0;
const that = this;
return {
next: function () {
if (index < that.name.length) {
return { done: false, value: that.name[index++] };
} else {
return { done: true, value: undefined };
}
},
};
},
};
const infoIterator = info[Symbol.iterator]();
console.log(infoIterator.next());
console.log(infoIterator.next());
console.log(infoIterator.next());
console.log(infoIterator.next());
// { done: false, value: 'abc' }
// { done: false, value: 'cba' }
// { done: false, value: 'nba' }
// { done: true, value: undefined }
内置可迭代对象
// 1、字符串
const message = "message";
console.log(message[Symbol.iterator]); // [Function: [Symbol.iterator]]
// 2、数组
const nums = [1, 2, 3, 4];
console.log(nums[Symbol.iterator]); // [Function: values]
// 3、arguements
function foo(x, y, z) {
console.log(arguments[Symbol.iterator]);// [Function: values]
}
foo();
// 4、Set(传入的是一个可迭代对象,返回的也是一个可迭代对象)
const set = new Set(message);
console.log(set[Symbol.iterator]);// [Function: values]
// 5、Map(返回的也是一个可迭代对象)
const map = new Map();
console.log(map[Symbol.iterator]);// [Function: entries]
可迭代对象的应用
-
for…of (必须是可迭代对象才能使用for…of)
-
Array.from(iterable | ArrayLike)
-
数组的展开语法
-
数组的解构语法
-
Promise类方法
-
创建Set数据结构
-
…
自定义类的可迭代
class Person {
constructor(name, age, friends) {
this.name = name;
this.age = age;
this.friends = friends;
}
makeFriend(name) {
this.friends.push(name);
}
[Symbol.iterator]() {
let index = 0;
return {
next: () => {
if (index < this.friends.length) {
return { done: false, value: this.friends[index++] };
} else {
return { done: true, value: undefined };
}
},
};
}
}
const person = new Person("fzb", 21, ["abc", "cba", "hgl"]);
const personIterator = person[Symbol.iterator]();
console.log(personIterator.next());
console.log(personIterator.next());
console.log(personIterator.next());
console.log(personIterator.next());
Generator
生成器的理解
生成器
是一个函数,可以控制函数内代码的执行流程。
生成器函数
和普通函数的区别:
- 在定义函数的时候,
生成器函数
需要在function
关键字后加*
生成器函数
可以控制函数内代码的执行逻辑,但普通函数不行。生成器函数
的返回值是一个迭代器
.
生成器函数的执行流程
yield后面跟着的值,将作为 迭代器.next返回对象的value值
return后面跟着的值将作为 迭代器.next最后一次返回对象的value值,同时done:true
其实还可以向生成器函数
内传参数
next方法
内传入的参数在上一个yield
内接收
第一个next方法一般不传参数,因为前面也没有yield,要传参数在获取迭代器的时候传入参数就行了
function* foo() {
console.log("函数内代码开始执行~");
const num1 = 100;
console.log("num1:", num1);
const n = yield num1;
console.log("我是第二的next内传入的参数:", n); // 我是第二的next内传入的参数: 10
const num2 = 200;
console.log("num2:", num2);
return num2;
}
const iterator = foo();
console.log(iterator.next());
console.log(iterator.next(10));
生成器的其他方法调用
return方法
提前终止生成器函数,返回传入的值
function* foo() {
console.log("函数内代码开始执行~");
const num1 = 100;
console.log("num1:", num1);
const n = yield num1;
// 相当于 return n
console.log("我是第二的next内传入的参数:", n);
const num2 = 200;
console.log("num2:", num2);
yield num2;
const num3 = 300;
console.log("num3:", num3);
}
const iterator = foo();
console.log(iterator.next());
console.log(iterator.return(10)); // 在使用return后 相当于传入参数后直接return
console.log(iterator.next());
throw方法
对上一次返回对象的值不满意,抛出错误,并且可以继续执行下面代码
function* foo() {
console.log("函数内代码开始执行~");
const num1 = 100;
console.log("num1:", num1);
try {
yield num1;
} catch (error) {
console.log(error);
}
const num2 = 200;
console.log("num2:", num2);
yield num2;
const num3 = 300;
console.log("num3:", num3);
}
const iterator = foo();
console.log(iterator.next());
console.log(iterator.throw("error message"));
console.log(iterator.next());
以上是关于Interator和Generator的主要内容,如果未能解决你的问题,请参考以下文章