Generator
Generator函数是ES6提供的一种异步编程解决方案,可以理解为Generator 函数是一个状态机,封装了多个内部状态。
执行 Generator 函数会返回一个遍历器对象
Generator 函数是一个普通函数,但是有两个特征。
一是,`function`关键字与函数名之间有一个星号;
二是,函数体内部使用`yield`表达式,定义不同的内部状态
实例:
function* helloWorldGenerator() {
yield 'hello';
yield 'world';
return 'ending';
}
var hw = helloWorldGenerator();
Generator 函数`helloWorldGenerator`,它内部有两个`yield`表达式(`hello`和`world`),即该函数有三个状态:
hello,world 和 return 语句(结束执行)
function* getval() {
yield 'lily';
yield 'tom';
return 'names';
}
var val = getval();
val.next();
val.next();
val.next();
yield 表达式
由于 Generator 函数返回的遍历器对象,只有调用`next`方法才会遍历下一个内部状态,所以其实提供了一种可以暂停
执行的函数。`yield`表达式就是暂停标志。
遍历器对象的`next`方法的运行逻辑如下。
(1)遇到`yield`表达式,就暂停执行后面的操作,并将紧跟在`yield`后面的那个表达式的值,作为返回的对象的
`value`属性值。
(2)下一次调用`next`方法时,再继续往下执行,直到遇到下一个`yield`表达式。
(3)如果没有再遇到新的`yield`表达式,就一直运行到函数结束,直到`return`语句为止,并将`return`语句
后面的表达式的值,作为返回的对象的`value`属性值。
(4)如果该函数没有`return`语句,则返回的对象的`value`属性值为`undefined`。
注:`yield`表达式后面的表达式,只有当调用`next`方法、内部指针指向该语句时才会执行
next 方法
`yield`表达式本身没有返回值,或者说总是返回`undefined`。`next`方法可以带一个参数,该参数就会被当作上一个
`yield`表达式的返回值。
实例:
function* f() {
for(var i = 0; true; i++) {
var reset = yield i;
if(reset) { i = -1; }
}
}
var g = f();
g.next()
g.next()
g.next(true)
async 函数
async 函数:是 Generator 函数的语法糖。(ES7新增)
`async`函数就是将 Generator 函数的星号(`*`)替换成`async`,将`yield`替换成`await`
实例:
async function async(){
await 'lily';
await 'tom';
return 'names';
}
`async`函数对 Generator 函数的改进,体现在以下四点。
(1)内置执行器:Generator 函数的执行必须靠执行器,所以才有了`co`模块,而`async`函数自带执行器。
也就是说,`async`函数的执行,与普通函数一模一样,只要一行。
(2)更好的语义:`async`和`await`,比起星号和`yield`,语义更清楚了。`async`表示函数里有异步操作,
`await`表示紧跟在后面的表达式需要等待结果。
(3)更广的适用性:`co`模块约定,`yield`命令后面只能是 Thunk 函数(有限函数)或 Promise 对象,而
`async`函数的`await`命令后面,可以是 Promise 对象和原始类型的值(数值、字符串和布尔值,但这时会自动转成
立即resolved 的 Promise 对象)
(4)返回值是 Promise:`async`函数的返回值是 Promise 对象,
const asyncReadFile = async function () {
const f1 = await readFile('/etc/fstab');
const f2 = await readFile('/etc/shells');
console.log(f1.toString());
console.log(f2.toString());
};
基本用法
`async`函数返回一个 Promise 对象,可以使用`then`方法添加回调函数。当函数执行的时候,一旦遇到`await`就会
先返回,等到异步操作完成,再接着执行函数体内后面的语句。
await作用:
`await`命令后面是一个 Promise 对象,返回该对象的结果。
如果不是 Promise 对象,就直接返回对应的值。
暂停键;
Proxy
Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改,
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一
种机制,可以对外界的访问进行过滤和改写
语法:
var proxy=new Proxy(target,handler);
target为拦截对象
handler是处理方法
Proxy 支持的拦截操作一览,一共 13 种。
- **get(target, propKey, receiver)** :拦截对象属性的读取,比如`proxy.foo`和`proxy['foo']`。
- **set(target, propKey, value, receiver)** :拦截对象属性的设置,比如`proxy.foo = v`或
`proxy['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)`、`for...in`循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而
`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)`。