ES6学习总结

开始正式进行对于react等JS的技术学习,第一步,需要学习对于ES6标准的学习。

  1. let语句:相似var,但是对于var定义的为全局变量而言,其let定义后会自身形成一个作用域,在此作用域中其变量发生作用。
ej.
for (let i = 0; i < 3; i++) {
  let i = 'abc';
  console.log(i);
}
// abc
// abc
// abc
  1. const语句:const声明一个只读的常量。一旦声明,常量的值就不能改变。
const PI = 3.1415;

对于PI进行赋值操作则会报错。

  1. 数组的解构赋值:
let a = 1;
let b = 2;
let c = 3;

等同于: let [a, b, c] = [1, 2, 3]; 此解构赋值可以用于对于变量的交换赋值和json对象的解析操作:

let jsonData = {
    id: 42,
    status: "OK",
    data: [867, 5309]
};
let { id, status, data: number } = jsonData;
console.log(id, status, number);
// 42, "OK", [867, 5309]
//遍历map
var map = new Map();
map.set('first', 'hello');
map.set('second', 'world');
for (let [key, value] of map) {
    console.log(key + " is " + value);
}
  1. 字符串方法
  2. 查找(字符串)
  3. includes():返回布尔值,表示是否找到了参数字符串。
  4. startsWith():返回布尔值,表示参数字符串是否在源字符串的头部。
  5. endsWith():返回布尔值,表示参数字符串是否在源字符串的尾部。 注意:这三个方法都支持第二个参数,表示开始搜索的位置。但是对于endsWith方法表示的是前n个字符
  6. 重复(字符串)
  7. repeat方法返回一个新字符串,表示将原字符串重复n次。'x'.repeat(3) // "xxx"
  8. 字符串补全
  9. padStart(),padEnd():padStart和padEnd一共接受两个参数,第一个参数用来指定字符串的最小长度,第二个参数是用来补全的字符串。'1'.padStart(10, '0') // "0000000001"
  10. 模板字符串
  11. 模板字符串(template string)是增强版的字符串,用反引号(`)标识。它可以当作普通字符串使用,也可以用来定义多行字符串,或者在字符串中嵌入变量,方法甚至于逻辑运算。
// 字符串中嵌入变量
var name = "Bob", time = "today";
`Hello ${name}, how are you ${time}?`
  • raw()
  • raw()方法:为基础string类型提供了此方法,String.raw方法,往往用来充当模板字符串的处理函数,返回一个斜杠都被转义(即斜杠前面再加一个斜杠)的字符串,对应于替换变量后的模板字符串

  • 数值方法

  • ES6将全局方法parseInt()和parseFloat(),移植到Number对象上面,行为完全保持不变。
  • Number.isFinite()用来检查一个数值是否为有限的(finite)
  • Number.isNaN()用来检查一个值是否为NaN
  • 它们与传统的全局方法isFinite()和isNaN()的区别在于,传统方法先调用Number()将非数值的值转为数值,再进行判断,而这两个新方法只对数值有效,非数值一律返回false。
  • Number.isInteger()用来判断一个值是否为整数。
  • ES6在Number对象上面,新增一个极小的常量Number.EPSILON。(2.220446049250313e-16主要目的是为了修正浮点运算时的精确度问题,对于进行的浮点运算,如果其值小于此常量,则认为其误差是可接受范围的)
  • ES6引入了Number.MAX_SAFE_INTEGER和Number.MIN_SAFE_INTEGER这两个常量,用来表示整数范围在-2^53到2^53之间的上下限。(Number.isSafeInteger()则是用来判断一个整数是否落在这个范围之内。)
  • Math.trunc方法用于去除一个数的小数部分,返回整数部分。
  • Math.sign方法用来判断一个数到底是正数、负数、还是零。
  • Math.cbrt方法用于计算一个数的立方根。
  • Math.clz32方法返回一个数的32位无符号整数形式有多少个前导0,因为JavaScript的整数使用32位二进制形式表示。
  • Math.imul方法返回两个数以32位带符号整数形式相乘的结果,返回的也是一个32位的带符号整数。
  • Math.fround方法返回一个数的单精度浮点数形式。
  • Math.hypot方法返回所有参数的平方和的平方根。
  • 数组方法
  • Array.from方法用于将两类对象转为真正的数组:类似数组的对象(array-like object)和可遍历(iterable)的对象(包括ES6新增的数据结构Set和Map,只要是部署了Iterator接口的数据结构,Array.from都能将其转为数组。Array.from还可以接受第二个参数,作用类似于数组的map方法,用来对每个元素进行处理,将处理后的值放入返回的数组。)。
//下面的例子将数组中布尔值为false的成员转为0。
Array.from([1, , 2, , 3], (n) => n || 0)
// [1, 0, 2, 0, 3]
  • 扩展运算符(...)也可以将某些数据结构转为数组。(扩展运算符背后调用的是遍历器接口(Symbol.iterator),如果一个对象没有部署这个接口,就无法转换。)
// arguments对象
function foo() {
      var args = [...arguments];
}
// NodeList对象
[...document.querySelectorAll('div')]
  • Array.of方法用于将一组值,转换为数组(这个方法的主要目的,是弥补数组构造函数Array()的不足。因为参数个数的不同,会导致Array()的行为有差异。)。
  • copyWithin方法,在当前数组内部,将指定位置的成员复制到其他位置(会覆盖原有成员),然后返回当前数组。也就是说,使用这个方法,会修改当前数组。
Array.prototype.copyWithin(target, start = 0, end = this.length)
//它接受三个参数。
//target(必需):从该位置开始替换数据。
//start(可选):从该位置开始读取数据,默认为0。如果为负值,表示倒数。
//end(可选):到该位置前停止读取数据,默认等于数组长度。如果为负值,表示倒数。
  • find方法,用于找出第一个符合条件的数组成员。它的参数是一个回调函数,所有数组成员依次执行该回调函数,直到找出第一个返回值为true的成员,然后返回该成员。如果没有符合条件的成员,则返回undefined。
  • findIndex方法的用法与find方法非常类似,返回第一个符合条件的数组成员的位置,如果所有成员都不符合条件,则返回-1。
[1, 5, 10, 15].find(function(value, index, arr) {
      return value > 9;
}) // 10
[1, 5, 10, 15].findIndex(function(value, index, arr) {
      return value > 9;
}) // 2
  • fill方法使用给定值,填充一个数组(fill方法还可以接受第二个和第三个参数,用于指定填充的起始位置和结束位置。)
['a', 'b', 'c'].fill(7, 1, 2)
// ['a', 7, 'c']
  • entries(),keys()和values()——用于遍历数组。
for (let [index, elem] of ['a', 'b'].entries()) {
      console.log(index, elem);
}
// 0 "a"
// 1 "b"
let letter = ['a', 'b', 'c'];
let entries = letter.entries();
console.log(entries.next().value); // [0, 'a']
console.log(entries.next().value); // [1, 'b']
console.log(entries.next().value); // [2, 'c']
  • Array.prototype.includes方法返回一个布尔值,表示某个数组是否包含给定的值,与字符串的includes方法类似。该方法属于ES7。
  • 数组的空位指,数组的某一个位置没有任何值。空位不是undefined。这里如果使用Array.from会将其值转为undefined。
  • 函数
  • ES6 允许为函数的参数设置默认值,即直接写在参数定义的后面。
function Point(x = 0, y = 0) {
  this.x = x;
  this.y = y;
}
var p = new Point();
p // { x: 0, y: 0 }
  • ES6 引入 rest 参数(形式为“...变量名”),用于获取函数的多余参数,这样就不需要使用arguments对象了。rest 参数搭配的变量是一个数组,该变量将多余的参数放入数组中。
// arguments变量的写法
function sortNumbers() {
  return Array.prototype.slice.call(arguments).sort();
}
// rest参数的写法
const sortNumbers = (...numbers) => numbers.sort();
  • 即使用扩展运算符(...)进行数组的展开可以用于数组的合并,扩展运算符可以与解构赋值结合起来,用于生成数组。扩展运算符还可以将字符串转为真正的数组。
// ES6的合并数组
[...arr1, ...arr2, ...arr3]
// [ 'a', 'b', 'c', 'd', 'e' ]
const [first, ...rest] = [1, 2, 3, 4, 5];
first // 1
rest  // [2, 3, 4, 5]
const [first, ...rest] = [];
first // undefined
rest  // []:
const [first, ...rest] = ["foo"];
first  // "foo"
rest   // []
[...'hello']
// [ "h", "e", "l", "l", "o" ]
//Map结构
let map = new Map([
  [1, 'one'],
  [2, 'two'],
  [3, 'three'],
]);
let arr = [...map.keys()]; // [1, 2, 3]
//Generator函数
var go = function*(){
  yield 1;
  yield 2;
  yield 3;
};
[...go()] // [1, 2, 3]
  • ES6允许使用“箭头”(=>)定义函数。
var f = () => 5;
// 等同于
var f = function () { return 5 };
var sum = (num1, num2) => num1 + num2;
// 等同于
var sum = function(num1, num2) {
      return num1 + num2;
};
// 用于简化回调函数
// 正常函数写法
var result = values.sort(function (a, b) {
  return a - b;
});
// 箭头函数写法
var result = values.sort((a, b) => a - b);

(1)函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象。 (2)不可以当作构造函数,也就是说,不可以使用new命令,否则会抛出一个错误。 (3)不可以使用arguments对象,该对象在函数体内不存在。如果要用,可以用Rest参数代替。 (4)不可以使用yield命令,因此箭头函数不能用作Generator函数。 *Tips:箭头函数可以让setTimeout里面的this,绑定定义时所在的作用域,而不是指向运行时所在的作用域。 箭头函数可以绑定this对象,大大减少了显式绑定this对象的写法 - 函数绑定运算符是并排的两个双冒号(::),双冒号左边是一个对象,右边是一个函数。该运算符会自动将左边的对象,作为上下文环境(即this对象),绑定到右边的函数上面。

foo::bar;
// 等同于
bar.bind(foo);
foo::bar(...arguments);
// 等同于
bar.apply(foo, arguments);
const hasOwnProperty = Object.prototype.hasOwnProperty;
function hasOwn(obj, key) {
  return obj::hasOwnProperty(key);
}
  • 对象
  • ES6 允许在对象之中,直接写变量。这时,属性名为变量名, 属性值为变量的值。
function f(x, y) {
  return {x, y};
}
// 等同于
function f(x, y) {
  return {x: x, y: y};
}
f(1, 2) // Object {x: 1, y: 2}
  • Object.is方法用来比较两个值是否严格相等,与严格比较运算符(===)的行为基本一致。
Object.is('foo', 'foo')
// true
Object.is({}, {})
// false
  • Object.assign方法用于对象的合并,将源对象(source)的所有可枚举属性,复制到目标对象(target)(其他类型的值(即数值、字符串和布尔值)不在首参数,也不会报错。但是,除了字符串会以数组形式,拷贝入目标对象,其他值都不会产生效果。)。
var v1 = 'abc';
var v2 = true;
var v3 = 10;
var obj = Object.assign({}, v1, v2, v3);
console.log(obj); // { "0": "a", "1": "b", "2": "c" }
  • 对象的每个属性都有一个描述对象(Descriptor),用来控制该属性的行为。Object.getOwnPropertyDescriptor方法可以获取该属性的描述对象。
  • __proto__属性(前后各两个下划线),用来读取或设置当前对象的prototype对象。(浏览器必须部署这个属性,其他运行环境不一定需要部署,而且新的代码最好认为这个属性是不存在的。因此,都不要使用这个属性,而是使用下面的Object.setPrototypeOf()(写操作)、Object.getPrototypeOf()(读操作)、Object.create()(生成操作)代替。)
  • prototype对象,返回参数对象本身。
// 格式
Object.setPrototypeOf(object, prototype)
// 用法
var o = Object.setPrototypeOf({}, null);
//等同于
function (obj, proto) {
        obj.__proto__ = proto;
        return obj;
}
- Object.getPrototypeOf(obj);该方法与Object.setPrototypeOf方法配套,用于读取一个对象的原型对象。
  • ES2017了跟Object.keys,配套的Object.values和Object.entries,作为遍历一个对象的补充手段,供for...of循环使用。
let {keys, values, entries} = Object;
let obj = { a: 1, b: 2, c: 3 };
for (let key of keys(obj)) {
  console.log(key); // 'a', 'b', 'c'
}
for (let value of values(obj)) {
  console.log(value); // 1, 2, 3
}
for (let [key, value] of entries(obj)) {
  console.log([key, value]); // ['a', 1], ['b', 2], ['c', 3]
}
  • ES2017 引入了Object.getOwnPropertyDescriptors方法,返回指定对象所有自身属性(非继承属性)的描述对象。
const obj = {
     foo: 123,
     get bar() { return 'abc' }
};
Object.getOwnPropertyDescriptors(obj)
// { foo:
//    { value: 123,
//      writable: true,
//      enumerable: true,
//      configurable: true },
//   bar:
//    { get: [Function: bar],
//      set: undefined,
//      enumerable: true,
//      configurable: true } }
  • 原始数据类型Symbol,表示独一无二的值。它是JavaScript语言的第七种数据类型
  • 对象的属性名现在可以有两种类型,一种是原来就有的字符串,另一种就是新增的Symbol类型。凡是属性名属于Symbol类型,就都是独一无二的,可以保证不会与其他属性名产生冲突。
  • Symbol值不是对象,所以不能添加属性。基本上,它是一种类似于字符串的数据类型。
  • Symbol函数的参数只是表示对当前 Symbol 值的描述,因此相同参数的Symbol函数的返回值是不相等的。
  • Symbol值可以显式转为字符串,bool,但是不能转换为数字等类型或者与其他类型的值进行运算,会报错。
  • 由于每一个Symbol值都是不相等的,这意味着Symbol值可以作为标识符,用于对象的属性名,就能保证不会出现同名的属性。但是对于这样的赋值操作,需要在读取值的时候讲symbol作为字符串,即使用xxx['symbol']的形式。
var mySymbol = Symbol();
var a = {};
a.mySymbol = 'Hello!';
a[mySymbol] // undefined
a['mySymbol'] // "Hello!"
//示例,使用symbol消除魔术字符串
var shapeType = {
  triangle: Symbol()
};
function getArea(shape, options) {
  var area = 0;
  switch (shape) {
    case shapeType.triangle:
      area = .5 * options.width * options.height;
      break;
  }
  return area;
}
getArea(shapeType.triangle, { width: 100, height: 100 });
  • Set和Map
  • ES6 提供了新的数据结构 Set。它类似于数组,但是成员的值都是唯一的,没有重复的值。Set 本身是一个构造函数,用来生成 Set 数据结构。(Set加入值的时候,不会发生类型转换,另外,两个对象总是不相等的。)
// 例一
var set = new Set([1, 2, 3, 4, 4]);
[...set]
// [1, 2, 3, 4]
// 例二
var items = new Set([1, 2, 3, 4, 5, 5, 5, 5]);
items.size // 5
// 例三
function divs () {
  return [...document.querySelectorAll('div')];
}
var set = new Set(divs());
set.size // 56
// 类似于
divs().forEach(div => set.add(div));
set.size // 56
  • Set.prototype.constructor:构造函数,默认就是Set函数。
  • Set.prototype.size:返回Set实例的成员总数。
  • add(value):添加某个值,返回Set结构本身。
  • delete(value):删除某个值,返回一个布尔值,表示删除是否成功。
  • has(value):返回一个布尔值,表示该值是否为Set的成员。
  • clear():清除所有成员,没有返回值。
s.add(1).add(2).add(2);
// 注意2被加入了两次
s.size // 2
s.has(1) // true
s.has(2) // true
s.has(3) // false
s.delete(2);
s.has(2) // false
  • Set结构的实例有四个遍历方法,可以用于遍历成员。
  • keys():返回键名的遍历器
  • values():返回键值的遍历器
  • entries():返回键值对的遍历器
  • forEach():使用回调函数遍历每个成员
let set = new Set(['red', 'green', 'blue']);
for (let item of set.keys()) {
  console.log(item);
}
// red
// green
// blue
for (let item of set.values()) {
  console.log(item);
}
// red
// green
// blue
for (let item of set.entries()) {
  console.log(item);
}
// ["red", "red"]
// ["green", "green"]
// ["blue", "blue"]
  • Map数据结构。它类似于对象,也是键值对的集合,但是“键”的范围不限于字符串,各种类型的值(包括对象)都可以当作键。
var map = new Map([
  ['name', '张三'],
  ['title', 'Author']
]);
map.size // 2
map.has('name') // true
map.get('name') // "张三"
map.has('title') // true
map.get('title') // "Author"
  • size属性size属性返回Map结构的成员总数。
  • set(key, value):set方法设置key所对应的键值,然后返回整个Map结构。如果key已经有值,则键值会被更新,否则就新生成该键。
  • get(key):get方法读取key对应的键值,如果找不到key,返回undefined。
  • has(key):has方法返回一个布尔值,表示某个键是否在Map数据结构中。
  • delete(key):delete方法删除某个键,返回true。如果删除失败,返回false。
  • clear():clear方法清除所有成员,没有返回值。
//map=>数组
let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
[...myMap]
// [ [ true, 7 ], [ { foo: 3 }, [ 'abc' ] ] ]
//数组=>map
new Map([[true, 7], [{foo: 3}, ['abc']]])
// Map {true => 7, Object {foo: 3} => ['abc']}
//Map=>json(两种形式,形式1)
function strMapToJson(strMap) {
  return JSON.stringify(strMapToObj(strMap));
}
let myMap = new Map().set('yes', true).set('no', false);
strMapToJson(myMap)
// '{"yes":true,"no":false}'
//Map=>json(两种形式,形式2,键名非字符串)
function mapToArrayJson(map) {
  return JSON.stringify([...map]);
}
let myMap = new Map().set(true, 7).set({foo: 3}, ['abc']);
mapToArrayJson(myMap)
// '[[true,7],[{"foo":3},["abc"]]]'
  • Proxy
  • Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。
var obj = new Proxy({}, {
  get: function (target, key, receiver) {
    console.log(`getting ${key}!`);
    return Reflect.get(target, key, receiver);
  },
  set: function (target, key, value, receiver) {
    console.log(`setting ${key}!`);
    return Reflect.set(target, key, value, receiver);
  }
});
//相当于重新了.运算符,在读取和写入数据的时候会自动触发改写后的方法
obj.count = 1
//  setting count!
++obj.count
//  getting count!
//  setting count!
//  2
  • 其形式为var proxy = new Proxy(target, handler);//(new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。)
  • get(target, propKey, receiver)拦截对象属性的读取,比如proxy.fooproxy['foo']。最后一个参数receiver是一个对象,可选。
  • set(target, propKey, value, receiver)拦截对象属性的设置,比如proxy.foo = vproxy['foo'] = v,返回一个布尔值。
  • has(target, propKey)拦截propKey in proxy的操作,返回一个布尔值。
  • deleteProperty(target, propKey)拦截delete proxy[propKey]的操作,返回一个布尔值。
  • ownKeys(target)拦截Object.getOwnPropertyNames(proxy)Object.getOwnPropertySymbols(proxy)Object.keys(proxy),返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。
  • getOwnPropertyDescriptor(target, propKey)拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
  • defineProperty(target, propKey, propDesc)拦截Object.defineProperty(proxy, propKey, propDesc)Object.defineProperties(proxy, propDescs),返回一个布尔值。
  • preventExtensions(target)拦截Object.preventExtensions(proxy),返回一个布尔值。
  • getPrototypeOf(target)拦截Object.getPrototypeOf(proxy),返回一个对象。
  • isExtensible(target)拦截Object.isExtensible(proxy),返回一个布尔值。
  • setPrototypeOf(target, proto)拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。
  • apply(target, object, args)拦截 Proxy 实例作为函数调用的操作,比如proxy(...args)proxy.call(object, ...args)proxy.apply(...)
  • construct(target, args)拦截 Proxy 实例作为构造函数调用的操作,比如new proxy(...args)。
  • Reflect
  • Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API(1. 将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。)。
  • Promise 对象
  • Promise 是异步编程的一种解决方案,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。
// ES6规定promise是一个构造函数
var promise = new Promise(function(resolve, reject) {
  // ... some code
  if (/* 异步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }
});
  • Promise构造函数接受一个函数作为参数,该函数的两个参数分别是resolve和reject。resolve函数的作用是,将Promise对象的状态从“未完成”变为“成功”(即从Pending变为Resolved),在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;reject函数的作用是,将Promise对象的状态从“未完成”变为“失败”(即从Pending变为Rejected),在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。Promise实例生成以后,可以用then方法分别指定Resolved状态和Reject状态的回调函数。
function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'done');
  });
}
timeout(100).then((value) => {
  console.log(value);
});
  • then方法返回的是一个新的Promise实例(注意,不是原来那个Promise实例)。因此可以采用链式写法,即then方法后面再调用另一个then方法。
getJSON("/post/1.json").then(function(post) {
  return getJSON(post.commentURL);
}).then(function funcA(comments) {
  console.log("Resolved: ", comments);
}, function funcB(err){
  console.log("Rejected: ", err);
});
//使用箭头函数来简化此代码,如下所示
getJSON("/post/1.json").then(
  post => getJSON(post.commentURL)
).then(
  comments => console.log("Resolved: ", comments),
  err => console.log("Rejected: ", err)
);
  • Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。
var promise = new Promise(function(resolve, reject) {
  throw new Error('test');
});
promise.catch(function(error) {
  console.log(error);
});
// Error: test
  • Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例。
// 生成一个Promise对象的数组
var promises = [2, 3, 5, 7, 11, 13].map(function (id) {
  return getJSON("/post/" + id + ".json");
});
Promise.all(promises).then(function (posts) {
  // ...
}).catch(function(reason){
  // ...
});
//promises是包含6个Promise实例的数组,只有这6个实例的状态都变成fulfilled,或者其中有一个变为rejected,才会调用Promise.all方法后面的回调函数。
  • Promise.race方法同样是将多个Promise实例,包装成一个新的Promise实例。 var p = Promise.race([p1, p2, p3]);上面代码中,只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的 Promise 实例的返回值,就传递给p的回调函数。
  • Promise.resolve方法,将现有对象转为Promise对象
  • Promise.reject(reason)方法也会返回一个新的 Promise 实例,该实例的状态为rejected。
  • 两个有用的附加方法(finally(末位总执行)和done(用于捕获所有的错误))
//done
Promise.prototype.done = function (onFulfilled, onRejected) {
  this.then(onFulfilled, onRejected)
    .catch(function (reason) {
      // 抛出一个全局错误
      setTimeout(() => { throw reason }, 0);
    });
};
//调用
asyncFunc().then(f1).catch(r1).then(f2).done();
//funally
Promise.prototype.finally = function (callback) {
  let P = this.constructor;
  return this.then(
    value  => P.resolve(callback()).then(() => value),
    reason => P.resolve(callback()).then(() => { throw reason })
  );
};
//调用
server.listen(0).then(function () { // run test}).finally(server.stop);
  • 遍历器(Iterator)
  • 就是这样一种机制。它是一种接口,为各种不同的数据结构提供统一的访问机制。任何数据结构只要部署Iterator接口,就可以完成遍历操作(即依次处理该数据结构的所有成员)。
  • Iterator的作用有三个:一是为各种数据结构,提供一个统一的、简便的访问接口;二是使得数据结构的成员能够按某种次序排列;三是ES6创造了一种新的遍历命令for...of循环,Iterator接口主要供for...of消费。
  • Generator 函数是 ES6 提供的一种异步编程解决方案
  • Generator 函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield语句,定义不同的内部状态(状态机)。
  • 调用Generator函数后,该函数并不执行,返回的也不是函数运行结果,而是一个指向内部状态的指针对象,也就是上一章介绍的遍历器对象(Iterator Object)。下一步,必须调用遍历器对象的next方法,使得指针移向下一个状态。也就是说,每次调用next方法,内部指针就从函数头部或上一次停下来的地方开始执行,直到遇到下一个yield语句(或return语句)为止。换言之,Generator函数是分段执行的,yield语句是暂停执行的标记,而next方法可以恢复执行。

链接