ES6-新内容(二)Proxy和Iterator

1.Proxy和Reflect拦截
2.Iterator遍历器

一、Proxy和Reflect

1.概念

Proxy代理,拦截作用。

2.语法

var proxy = new Proxy(target, handler);

target是目标对象,handler是拦截不同方法的声明。
handler事件:getset、has、deleteProperty、ownKeys、getOwnPropertyDescriptor、defineProperty、preventExtensions、getPrototypeOf、isExtensible、setPrototypeOf、applyconstruct
具体每种事件对应什么方法,详见http://caibaojian.com/es6/proxy.html

3.

Proxy.revocable方法返回一个可取消的Proxy实例。

4.this指向

在 Proxy 代理的情况下,目标对象内部的this关键字会指向 Proxy 代理。

5.Reflect概念

修改了Object的一些方法,改为函数调用,返回布尔值更为合理,为Proxy操作对象的事件提供便利。

6.Reflect方法

同Proxy的handler支持的事件一致。

二、Iterator遍历器

1.作用

  • 为四种数据集合(Array/Object/Map/Set)提供统一的接口机制。
  • 使得数据结构的成员能够按某种次序排列。
  • ES6创造了一种新的遍历命令for…of循环,Iterator接口主要供for…of消费。

2.遍历过程

(1)创建一个指针对象,指向当前数据结构的起始位置。也就是说,遍历器对象本质上,就是一个指针对象
(2)第一次调用指针对象的next方法,可以将指针指向数据结构的第一个成员。
(3)第二次调用指针对象的next方法,指针就指向数据结构的第二个成员。
(4)不断调用指针对象的next方法,直到它指向数据结构的结束位置。
每一次调用next方法,都会返回数据结构的当前成员的信息。

3.原理

一个数据结构只要具有Symbol.iterator属性,就可以认为是“可遍历的”(iterable)。
遍历器对象的根本特征就是具有next方法。每次调用next方法,都会返回一个代表当前成员的信息对象,具有value和done两个属性。
举例:

const obj = {
  [Symbol.iterator] : function () {
    return {
      next: function () {
        return {
          value: 1,
          done: true
        };
      }
    };
  }
};

4.调用Iterator接口的场合

1)解构赋值

对数组和Set结构进行解构赋值时,会默认调用Symbol.iterator方法。

let set = new Set().add('a').add('b').add('c');

let [x,y] = set;
// x='a'; y='b'

let [first, ...rest] = set;
// first='a'; rest=['b','c'];
2)扩展运算符
3)yield*
4)其他场合

由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用了遍历器接口。

  • for…of
  • Array.from()
  • Map(), Set(), WeakMap(), WeakSet()
  • Promise.all()
  • Promise.race()

三、generator函数

是ES6提供的一种异步编程解决方案,语法行为与传统函数完全不同。

1.理解

  • 语法上,首先可以把它理解成,Generator函数是一个状态机,封装了多个内部状态。
  • 形式上,Generator函数是一个普通函数,但是有两个特征。一是,function关键字与函数名之间有一个星号;二是,函数体内部使用yield语句,定义不同的内部状态

2.返回

返回一个状态对象{value:'1',done:'false'}
只能通过调用next方法进入下一个状态。
举例:

function* helloWorldGenerator() {
  yield 'hello';
  yield 'world';
  return 'ending';
}
var hw = helloWorldGenerator();
hw.next();// { value: 'hello', done: false }

3.yield语句

运行逻辑:
(1)遇到yield语句,就暂停执行后面的操作,并将紧跟在yield后面的那个表达式的值,作为返回的对象的value属性值。
(2)下一次调用next方法时,再继续往下执行,直到遇到下一个yield语句。
(3)如果没有再遇到新的yield语句,就一直运行到函数结束,直到return语句为止,并将return语句后面的表达式的值,作为返回的对象的value属性值。
(4)如果该函数没有return语句,则返回的对象的value属性值为undefined。

注意:

  • 只能出现在generator函数中,函数作为参数的情况中也不能使用。
  • 如果用在一个表达式之中,必须放在圆括号里面。
    console.log('Hello' + (yield 123)); // OK
  • 用作函数参数或赋值表达式的右边,可以不加括号。
foo(yield 'a', yield 'b'); // OK
let input = yield; // OK

4.yield*

如果在Generater函数内部,调用另一个Generator函数,默认情况下是没有效果的。
这个就需要用到yield*语句,用来在一个Generator函数里面执行另一个Generator函数。

function* foo() {
  yield 'a';
  yield 'b';
}
function* bar() {
  yield 'x';
  yield* foo();
  yield 'y';
}
// 等同于
function* bar() {
  yield 'x';
  yield 'a';
  yield 'b';
  yield 'y';
}
function* gen(){
  yield* ["a", "b", "c"];
}
gen().next() // { value:"a", done:false }

yield命令后面如果不加星号,返回的是整个数组,加了星号就表示返回的是数组的遍历器对象。

5.与Iterator接口的关系

iterator对象最重要的Symbol.iterator属性,就是调用next()方法遍历数组中下一个对象,并返回{value:’’,done:false}遍历器对象。这可以通过generator函数实现。
可以把Generator赋值给对象的Symbol.iterator属性,从而使得该对象具有Iterator接口。

6.next

yield句本身没有返回值,或者说总是返回undefined。next方法可以带一个参数,该参数就会被当作上一个yield语句的返回值。

7.函数

throw
在函数体外抛出错误,然后在Generator函数体内捕获。
return
可以返回给定的值,并且终结遍历Generator函数。

8.其他

返回的总是遍历器对象,而不是this对象。
Generator函数也不能跟new命令一起用,会报错。
Generator是实现状态机的最佳结构。

9.协程

可以理解成“协作的线程”或“协作的函数”。协程既可以用单线程实现,也可以用多线程实现。
从实现上看,在内存中,子例程只使用一个栈(stack),而协程是同时存在多个栈,但只有一个栈是在运行状态,也就是说,协程是以多占用内存为代价,实现多任务的并行。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值