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),而協程是同時存在多個棧,但只有一個棧是在運行狀態,也就是說,協程是以多佔用內存爲代價,實現多任務的並行。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章