JS 迭代器(ITERATION)和生成器(GENERATOR)

news/2024/7/3 14:51:58 标签: js, iterator, generator, javascript

JS Learning Note -- Iteration and spread operation

  • Iteration
    • First question, what is the Iteration?
    • Iteration and spread operators in ES6
    • The Iterator Protocol
    • Customize Iterator
    • Early termination of iterators
  • Generator
    • Basic
    • Interrup ting execution with “yield”
    • Using a generator as the default iterator

Iteration

First question, what is the Iteration?

  In the dictionary, ‘iteration’ means ‘the repetition of a process or utterance’.
And in a program, it equals that repeat the code segment in order.

  Let me give you an example:

javascript">for(let i = 0; i <= 10; i++){
	console.log(i);
}

this is the easiest iteration, or one of the easiest.

  So if you do not have any idea about how that code work, I suggest you to learn more basic knowledge about JS.

Iteration and spread operators in ES6

  ECMAScript 6 introduced iterators and the spread operator, which are especially useful in the context of collection reference types.
  And many built-in types implement a default iterator:

  • Array
  • All typed arrays
  • String
  • Map
  • Set
  • The arguments object
  • Some Dom collection types like NodeList

  In that case, there is no doubt that all support ordered iteration and can be passed to a for…of loop:
  eg.

javascript">let arr = ['a', 'b', 'c'];
for (let str of arr){
	console.log(str);
}

  Dose it looks so familiar?Yes, you may have use that loop for may times.

  But do you know how it worked?

The Iterator Protocol

  The Iterator API uses a next() method to advance through the iterable.
  Each successive time next() is invoked, it will return an IteratorResult object containing the next value in the iterator.

  The next() method returns an object with two projects:done(boolean) and value(next value/ undefined)

  If done is true, that state is termed “exhaustion.”
  eg in document:

javascript">// Iterable object
let arr = ['foo', 'bar'];

// Iterator factory
console.log(arr[Symbol.iterator]); // f values() { [native code] }

// Iterator
let iter = arr[Symbol.iterator]();
console.log(iter); // ArrayIterator {}

// Performing iteration
console.log(iter.next()); // { done: false, value: 'foo' }
console.log(iter.next()); // { done: false, value: 'bar' }
console.log(iter.next()); // { done: true, value: undefined }

  Once the iterator reaches the done:true statr, invoking next() is idempotent

javascript">let arr = ['foo'];
let iter = arr[Symbol.iterator]();
console.log(iter.next()); // { done: false, value: 'foo' }
console.log(iter.next()); // { done: true, value: undefined } 
console.log(iter.next()); // { done: true, value: undefined }

  Different instances are not aware of each other and will independently traverse the iterable

javascript">let arr = ['foo', 'bar'];
let iter1 = arr[Symbol.iterator](); 
let iter2 = arr[Symbol.iterator]();

console.log(iter1.next()); // { done: false, value: 'foo' }
console.log(iter2.next()); // { done: false, value: 'foo' } 
console.log(iter2.next()); // { done: false, value: 'bar' }
console.log(iter1.next()); // { done: false, value: 'bar' }

Customize Iterator

   And there is a customize iterator
eg:

javascript">
class Counter {
 constructor(limit) {
  this.limit = limit;
 }

 [Symbol.iterator]() {
  let count = 1,
    limit = this.limit;
  return {
   next() {
    if (count <= limit) {
     return { done: false, value: count++ };
    } else {
     return { done: true, value: undefined };
    }
   }
  };
 }
}

let counter = new Counter(3);

for (let i of counter) { console.log(i); }
// 1
// 2
// 3
for (let i of counter) { console.log(i); }
// 1
// 2
// 3

iterators_134">Early termination of iterators

  A for…of loop exits early via break, continue, return, or throw.

javascript">class Counter {
 constructor(limit) {
  this.limit = limit;
 }

 [Symbol.iterator]() {
  let count = 1,
    limit = this.limit;
  return {
   next() {
    if (count <= limit) {
     return { done: false, value: count++ };
    } else {
     return { done: true };
    }
   },
   return() {
    console.log('Exiting early');
    return { done: true };
   }
  };
 }
}


let counter1 = new Counter(5);

for (let i of counter1) {
 if (i > 2) {
  break; 
 }
 console.log(i);
}
// 1
// 2
// Exiting early


let counter2 = new Counter(5);

try {
 for (let i of counter2 {
  if (i > 2) {
   throw 'err'; 
  }
  console.log(i);
 }
} catch(e) {}
// 1
// 2
// Exiting early


let counter3 = new Counter(5);

let [a, b] = counter3;
// Exiting early

  If an iterator is not closed, then you are able to pick up iteration where you left off. For example, Array Iterators are not closable:

javascript">
let a = [1, 2, 3, 4, 5];
let iter = a[Symbol.iterator]();

for (let i of iter) {
 console.log(i);
 if (i > 2) {
  break
 }
}
// 1
// 2
// 3

for (let i of iter) {
 console.log(i);
}
// 4
// 5

Generator

  Generators are a delightfully flexible construct introduced in the ECMAScript 6 specification that offers the ability to pause and resume code execution inside a single function block.

Basic

  Generators take the form of a function, and the generator designation is performed with an asterisk

javascript">// Generator function declaration
function* generatorFn() {}

// Generator function expression
let generatorFn = function* () {}

// Object literal method generator function
let foo = {
 * generatorFn() {}
}

// Class instance method generator function
class Foo {
 * generatorFn() {}
}

// Class static method generator function
class Bar {
 static * generatorFn() {}
}

Interrup ting execution with “yield”

  The yield keyword allows generators to stop and start execution, and it is what makes generators truly useful. Generator functions will proceed with normal execution until they encounter a yield keyword.

  eg

javascript">function* generatorFn() {
 yield 'foo';
 yield 'bar';
 return 'baz';
}

let generatorObject = generatorFn();

console.log(generatorObject.next()); // { done: false, value: 'foo' } 
console.log(generatorObject.next()); // { done: false, value: 'bar' } 
console.log(generatorObject.next()); // { done: true, value: 'baz' } 

  The yield keyword can be simultaneously used as both an input and an output, as is shown in the following example:

javascript">function* generatorFn() {
 return yield 'foo';
}

let generatorObject = generatorFn();

console.log(generatorObject.next());      // { done: false, value: 'foo' }
console.log(generatorObject.next('bar')); // { done: true, value: 'bar' } 

  The yield keyword is not limited to a one-time use. An infinite counting generator function can be defined as follows:

javascript">function* generatorFn() {
 for (let i = 0;;++i) {
  yield i;
 }
}

let generatorObject = generatorFn();

console.log(generatorObject.next().value); // 0
console.log(generatorObject.next().value); // 1
console.log(generatorObject.next().value); // 2
console.log(generatorObject.next().value); // 3
console.log(generatorObject.next().value); // 4
console.log(generatorObject.next().value); // 5 
...

generator_as_the_default_iterator_300">Using a generator as the default iterator

  Because generator objects implement the Iterable interface, and because both generator functions and the default iterator are invoked to produce an iterator, generators are exceptionally well suited to be used as default iterators.

eg

javascript">class Foo {
 constructor() {
  this.values = [1, 2, 3];
 }
 * [Symbol.iterator]() {
  yield* this.values;
 }
}

const f = new Foo();

for (const x of f) {
 console.log(x);
}
// 1
// 2
// 3

  NOTE:If the generator object has not yet begun execution, calling throw() cannot be caught inside the function because the error is thrown from outside the function block.

  If this blog helps you, can you give a like ! ! Thank you ! !


http://www.niftyadmin.cn/n/1485335.html

相关文章

不同网站不同网卡_角点科技分析营销型网站与普通网站的不同之处

营销型网站与普通网站的区别?现在很多企业都意识到了网站的重要性&#xff0c;但是在搭建网站的时候因为对网站建设这个行业并不是很了解&#xff0c;就会纠结是搭建普通的网站还是搭建营销型网站&#xff0c;接下来角点科技的小编就来和大家聊聊营销型网站与普通网站的区别。…

mysql 字段长度变更_mysql中利用sql语句修改字段名称,字段长度等操作

1.修改字段的长度语法&#xff1a;ALTER TABLE 表名 MODIFY COLUMN 字段名 数据类型(修改后的长度)例子&#xff1a;将字段的长度由10改为20ALTER TABLE attence MODIFY COLUMN id INT(20)2.修改字段的名称语法&#xff1a;alter table change 。例子&#xff1a;将字段attenc…

React Table dataSource 更新,Table未重新渲染

例子 直接给出未更新例子 可能跟你所写的代码不一样&#xff0c;但是可以参考看看 const [tableData,settableData]useState(Array)const columns[ ... ]let change(value)>{//*let tabledatatableDatatabledata.push(value)settableData(tabledata)... }...return(<Ta…

cgi web 调用多次启动_SpringCloud 基础教程(七)-Feign声明式服务调用

我的博客&#xff1a;兰陵笑笑生,欢迎浏览博客&#xff01;关注公众号&#xff1a;"程序员笑笑生"&#xff0c; 回复 "Spring Cloud"、"Spring Boot" 获取 全套 视频教程&#xff01;时间有限&#xff01;可扫描文章下方二维码&#xff01;上一章…

ANT Form 骚操作之动态增减

ANT Form复杂动态增减表单项 这里直接借用官网的例子讲解一下 import React from react; import ReactDOM from react-dom; import antd/dist/antd.css; import ./index.css; import { Form, Input, Button, Space, Select } from antd; import { MinusCircleOutlined, PlusO…

postgresql 触发器跨服务器_Linux系统:Centos7下搭建PostgreSQL关系型数据库

一、PostgreSQL简介1、数据库简介PostgreSQL是一个功能强大的开源数据库系统&#xff0c;具有可靠性、稳定性、数据一致性等特点&#xff0c;且可以运行在所有主流操作系统上&#xff0c;包括Linux、Unix、Windows等。PostgreSQL是完全的事务安全性数据库&#xff0c;完整地支持…

mac系统outlook配置服务器通讯录_云服务器 云操作系统 云数据库 常用的配置功能需求说明...

云服务器的功能要求&#xff1a;(1)支持虚拟机底层资源弹性分配、虚拟网络管理、以及在线迁移&#xff1b;(2)支持用户突发的大量资源的弹性需求&#xff1b;(3)支持消除系统热点&#xff0c;提高虚拟机中运行的应用程序性能&#xff1b;(4)至少支持普通云盘(采用普通云盘)和高…

python 依据某几列累加求和_均值高斯最大最小滤波原理及python实现

笔记&#xff1a;常用的图像滤波方法以及python实现&#xff0c;包括&#xff1a;均值滤波、高斯滤波、最大值滤波、最小值滤波。之前写过一篇图像增强的文章&#xff0c;但是最后得到的增强结果包含很多噪声点&#xff08;某师兄指出的&#xff09;。所以今天来用滤波算法去除…