1. 程式人生 > >ES6筆記三

ES6筆記三

es6

yield*語句

如果yield命令後面跟的是一個遍歷器,需要在yield命令後面加上星號,表明它返回的是一個遍歷器。這被稱為yield*語句

Generator是一個普通函數,但是有兩個特征。一是,function命令與函數名之間有一個星號;二是,函數體內部使用yield語句,定義遍歷器的每個成員,即不同的內部狀態(yield語句在英語裏的意思就是“產出”)。



ES6的Promise對象是一個構造函數,用來生成Promise實例。下面是Promise對象的基本用法。

var promise = new Promise(function(resolve, reject) {
  if (/* 異步操作成功 */){
    resolve(value);
  } else {
    reject(error);
  }});
  
  promise.then(function(value) {
  // success}, function(value) {
  // failure});


var getJSON = function(url) {
  var promise = new Promise(function(resolve, reject){
    var client = new XMLHttpRequest();
    client.open("GET", url);
    client.onreadystatechange = handler;
    client.responseType = "json";
    client.setRequestHeader("Accept", "application/json");
    client.send();

    function handler() {
      if (this.status === 200) { 
              resolve(this.response); 
          } else { 
              reject(new Error(this.statusText)); 
          }
    };
  });
  return promise;
  };
  
  getJSON("/posts.json").then(function(json) {
      console.log(‘Contents: ‘ + json);
      }, function(error) {
  console.error(‘出錯了‘, error);});


generator


function* helloWorldGenerator() {
  yield ‘hello‘;
  yield ‘world‘;
    return ‘ending‘;
}

var hw = helloWorldGenerator();

hw.next() // { value: ‘hello‘, done: false }
hw.next() // { value: ‘world‘, done: false }
hw.next() // { value: ‘ending‘, done: true }
hw.next() // { value: undefined, done: true }



function* foo(x) {
  var y = 2 * (yield (x + 1));
  var z = yield (y / 3);
  return (x + y + z);
 }
 
 var it = foo(5);
 it.next()// { value:6, done:false }
 it.next(12)// { value:8, done:false }
 it.next(13)// { value:42, done:true }
 由於next方法的參數表示上一個yield語句的返回值,所以第一次使用next方法時,不能帶有參數



function *foo() {
  yield 1;
  yield 2;
  yield 3;
  yield 4;
  yield 5;
  return 6;}
  
  for (let v of foo()) {
      console.log(v);
  }
  
  // 1 2 3 4 5


function* fibonacci() {
    let [prev, curr] = [0, 1];
    for (;;) {
        [prev, curr] = [curr, prev + curr];
        yield curr;
    }
}

for (let n of fibonacci()) {
    if (n > 1000) break;
    console.log(n);
}


var g = function* () {
    while (true) {
        try {
            yield;
        } catch (e) {
            if (e != ‘a‘) {
                throw e;
            }
            console.log(‘內部捕獲‘, e);
        }
    }
  };
  
  var i = g(); 
  i.next();
  try {
    i.throw(‘a‘);
    i.throw(‘b‘);
   } catch (e) {
    console.log(‘外部捕獲‘, e);
    }
    // 內部捕獲 a
    // 外部捕獲 b


foo(‘a‘, function (a) {
    if (a.error) {
        throw new Error(a.error);
    }

    foo(‘b‘, function (b) {
        if (b.error) {
            throw new Error(b.error);
        }

        foo(‘c‘, function (c) {
            if (c.error) {
                throw new Error(c.error);
            }

            console.log(a, b, c);
        });
    });});

使用Generator函數可以大大簡化上面的代碼。

function* g(){
  try {
        var a = yield foo(‘a‘);
        var b = yield foo(‘b‘);
        var c = yield foo(‘c‘);
    } catch (e) {
        console.log(e);
    }

  console.log(a, b, c);}





let delegatedIterator = (function* () {
  yield ‘Hello!‘;
  yield ‘Bye!‘;}());
  
let delegatingIterator = (function* () {
  yield ‘Greetings!‘;
  yield* delegatedIterator;
  yield ‘Ok, bye.‘;}());
  
for(let value of delegatingIterator) {
  console.log(value);}
  
  // "Greetings!
  // "Hello!"
  // "Bye!"
  // "Ok, bye."



如果yield*後面跟著一個數組,就表示該數組會返回一個遍歷器,因此就會遍歷數組成員。

function* gen(){
  yield* ["a", "b", "c"];}
  
 gen().next() 
 
 // { value:"a", done:false }

上面代碼中,yield命令後面如果不加星號,返回的是整個數組,加了星號就表示返回的是數組的遍歷器。



yield*命令可以很方便地取出嵌套數組的所有成員。

function* iterTree(tree) {
  if (Array.isArray(tree)) {
    for(let i=0; i < tree.length; i++) {
      yield* iterTree(tree[i]);
    }
  } else {
    yield tree;
  }
}

const tree = [ ‘a‘, [‘b‘, ‘c‘], [‘d‘, ‘e‘] ];

for(let x of iterTree(tree)) {
  console.log(x);
 }
 // a
 // b
 // c
 // d
 // e



下面是一個稍微復雜的例子,使用yield*語句遍歷完全二叉樹。

// 下面是二叉樹的構造函數,
// 三個參數分別是左樹、當前節點和右樹
function Tree(left, label, right) {
  this.left = left;
  this.label = label;
  this.right = right;
}

// 下面是中序(inorder)遍歷函數。
// 由於返回的是一個遍歷器,所以要用generator函數。
// 函數體內采用遞歸算法,所以左樹和右樹要用yield*遍歷

function* inorder(t) {
  if (t) {
    yield* inorder(t.left);
    yield t.label;
    yield* inorder(t.right);
  }
}

// 下面生成二叉樹
function make(array) {
  // 判斷是否為葉節點  
  if (array.length == 1) 
      return new Tree(null, array[0], null);
  return new Tree(make(array[0]), array[1], make(array[2]));
 }
 
 let tree = make([[[‘a‘], ‘b‘, [‘c‘]], ‘d‘, [[‘e‘], ‘f‘, [‘g‘]]]);
 
 // 遍歷二叉樹
 var result = [];
 for (let node of inorder(tree)) {
  result.push(node); 
 }
 
 result
 // [‘a‘, ‘b‘, ‘c‘, ‘d‘, ‘e‘, ‘f‘, ‘g‘]





































ES6筆記三