ES6生成器總結
ES6生成器總結
一、生成器的個人理解
首先什麼是生成器:生成器就是Es6中用來設定迭代器的一個函式,我們就可以這樣理解:生成器最終生成的就是迭代器。
生成器:生成器中存在一個iterator介面,也就是說,生成器本身是可以進行迭代的,也就是創造出一個生成器,就相當於建立一個迭代器。關於生成器的用途,對於一些沒有設定迭代器介面的資料型別,我們可以使用生成器來自定義生成一個迭代器,從而進行迭代。
以上便是我對於生成器本身的理解,下面講解具體的語法。
二、生成器的一些屬性
//生成器的宣告
<script>
function* generator(){
}
let test = generator();
console.log(test);
</script>
//生成器中的yield關鍵字
<script>
function* Generator(){
yield 100;
yield 200;
yield 300;
yield 400;
}
let test = Generator();
console.log(test.next());
console.log(test.next());
console.log(test.next());
console.log(test.next());
console.log(test.next());
console.log(test.next());
console.log(test.next());
</script>
最終結果:
解析:由於生成器例項化物件的原型中存在next(),當執行next(),就會根據yield進行迭代。
<script>
function* Generator(){
yield 100;
yield 200;
yield 300;
yield 400;
}
let test = Generator();
console.log(test[Symbol.iterator]);
</script>
又是上面的程式碼可以看出這個生成器存在Symbol.iterator介面,所以可以將其看成一個迭代器
生成器只會在使用初次呼叫函式的時候執行
<script>
function* Generator(){
console.log("初次執行函式");
yield 100;
yield 200;
yield 300;
yield 400;
}
let test = Generator();
console.log(test.next());
</script>
執行結果是:
在生成器中也會有介面,但是他們預設的迭代器是自引用的,所以下面兩種迭代方式得到相同的結果
<script>
function* Generator(){
yield 100;
yield 200;
yield 300;
yield 400;
}
let test = Generator();
// for(const x of test){
// console.log(x);
// }
for(const x of test[Symbol.iterator]()){
console.log(x);
}
</script>
結果是:
生成器物件區分作用域
<script>
function* Generator() {
yield 100;
yield 200;
yield 300;
yield 400;
}
let test_1 = Generator();
let test_2 = Generator();
console.log(test_1.next());
console.log(test_2.next());
console.log(test_1.next());
console.log(test_2.next());
</script>
解析:生成器是按照遊標進行輸出的,也就是但是當作用域不同,兩者的遊標互相不影響。
結果:
實現yield關鍵字輸出輸入
<script>
function* Generator() {
console.log(yield 100);
console.log(yield 200);
console.log(yield 300);
console.log(yield 400);
}
let test = Generator();
console.log(test.next("foo"));
console.log(test.next("bar"));
console.log(test.next("btz"));
console.log(test.next('set'));
console.log(test.next("map"));
</script>
結果:
這裡當我們傳入第一個的時候,並沒有輸出,這是當我們執行第一個的next()的時候,相當於去開啟執行這個函式,但是這個值並不傳給yield,但是當執行第二個yield的時候,這個yield接收到傳給的值並輸出。
yield*的使用
<script>
// function* Generator() {
// yield* [1, 2, 3, 4, 5];
// }
// let test = Generator();
// for (const x of test) {
// console.log(x);
// }
function* Generator(){
let arr = [1,2,3,4,5];
for(const x in arr){
yield arr[x];
}
}
let test = Generator();
for (const x of test[Symbol.iterator]()){
console.log(x);
}
//1,2,3,4,5
</script>
以上兩個方法進行迭代,都可以得到相同的結果,yiled*就相當於結構的思想。
yield* 的值最終返回的一定是undefined
<script>
function* Generator(){
console.log(yield* [1,2,3,4,5]);;
}
let test = Generator();
for (const x of test[Symbol.iterator]()){
console.log(x);
}
</script>
最終結果:
其實這裡可以這樣想yield * [1,2,3,4]就等價於 yield 1;yield 2,yield 3;yield 4;由於沒有給yield傳值,所以列印出來的是undefined。
yiled實現遞迴
<script>
function* Generator(n) {
if (n > 0) {
yield* Generator(n - 1);
yield n;
}
}
let text = Generator(10);
for (const x of text) {
console.log(x);
}
//1,2,3,4,5,6,7,8,9,10
</script>
yiled*後面必須接上一個具有iterator介面的資料型別
<script>
//第一種
function* gener_1(){
yield* [1,5,6,3,10];
}
function* gener_2(){
yield* gener_1();
}
for(const x of gener_2()){
console.log(x);
}
//1,5,6,3,10
</script>
這裡我們實現手寫三種迭代介面,這三種從上往下更加規範,簡單
<script>
class Gener {
constructor() {
this.value = [1, 2, 3, 4, 5];
};
[Symbol.iterator]() {
let index = 0;
let value = this.value;
return {
next() {
if (index < value.length) {
return {
value: value[index++],
done: false,
}
}
else {
return {
value: undefined,
done: true
}
}
}
}
}
}
let test = new Gener();
for (const x of test) {
console.log(x);
}
//第二種
class Gener{
constructor() {
this.value = [1,2,3,4,5];
}
*[Symbol.iterator](){
for(const x of this.value){
yield x;
}
}
}
let test = new Gener();
for (const x of test){
console.log(x);
}
// 第三種
class Gener{
constructor(){
this.value = [1,2,3,4,5];
}
*[Symbol.iterator](){
yield* this.value;
}
}
let test = new Gener();
for(const x of test){
console.log(x);
}
</script>
這三種最終的結果都是一樣的,為什麼要設定[Symbol.iteerator],是因為class物件中不可以進行迭代。
return方法
<script>
function * text(){
yield* [1,2,3,4,5];
}
let g = text();
console.log(g.return("3"));
</script>
在這裡執行return()的時候,就會返回其中傳入return的值,並且將其done設定為true
。
關於生成器中的throw()
<script>
function* text() {
for (const x of [1, 2, 3]) {
try {
yield x;
}
catch {
console.log("這是一個錯誤");
}
}
}
let test = text();
console.log(test.next());
console.log(test.throw("hhhh"));
console.log(test.next());
console.log(test.next());
</script>
解析:這裡一般執行throw()的時候,都會伴隨著try…catch一起使用。當執行這個throw()函式的時候,就相當於傳一個錯誤,所以就不會執行try中的語句,而是執行catch中的語句。然後不會像return()一樣直接退出迭代,throw()會跳過這個進入下一個。
以上便是我對於ES6的生成器的總結,以及自己的理解。總結出來時間已經比較晚了,加油,明天進入物件導向。
相關文章
- 【ES6總結】
- ES6使用總結
- ES6 部分總結
- ES6新特性總結
- ES6學習總結
- es6語法總結
- ES6常用語法總結
- ES6核心知識總結
- es6,async簡單總結
- es6類宣告,class總結
- 年底面試之es6總結面試
- ES6 變數作用域總結變數
- ES6個人初學總結-XY
- 帶你總結ES6的特性
- ES6箭頭函式總結函式
- ES6常見面試題總結面試題
- ES6常用的新特性總結
- ES6 語法學習總結
- 【ES6基礎】生成器(Generator)
- python迭代器和生成器的總結Python
- ES6常用知識點總結(上)
- ES6 export && export default 差異總結Export
- ES6常用知識點總結(下)
- ES6 let聲名變數總結變數
- ES6語言特性的總結(3)
- ES6語言特性的總結(1)
- ES6語言特性的總結(2)
- es6新語法新特性總結(上)
- ES6的Promise知識點總結Promise
- ES6生成器函式generator函式
- 分散式ID生成器的解決方案總結分散式
- let & const —— ES6基礎總結(二)
- 簡單總結es6箭頭符號符號
- ES6規範import和export用法總結ImportExport
- es6、7、8、9新語法新特性-總結
- ES6模組(Module)載入知識總結(一)
- 探索es6系列之—-Generator生成器函式函式
- 淺談ES6中迭代器和生成器