ES6迭代器(interator)和for...of...循環

ES6迭代器(interator)和for...of...循環

或許在寫ES6的代碼的時候,你可能沒有感受有用過迭代器這個東西,但是ES6中的for...of...循環咱們都不陌生,而for...of...循環的必要條件就是必須知足被循環的對象實現了迭代器接口才行。例子以下:數組

Exampleapp

var a = [1,2,3];
var b = {
    name:'arvin',
    age:30
}
for(var i of a){
    console.log(i);     // 結果依次是:1,2,3
}
for(var j of b){
    console.log(j);     // TypeError: b[Symbol.iterator] is not a function
}

代碼解讀:對於上面代碼的結果咱們基本都知道,但是爲何是這個結果就不會很懂了。從代碼的結果能夠看出,for...of...循環可行的條件是須要被循環對象實現一個以Symbol.iterator爲方法屬性才行。而數組對象是默認實現了該方法的,因此並未報錯。如今咱們就來具體實現一下這個迭代器接口。函數

Exampleui

var b = {
    name:'arvin',
    age:30
}
Object.defineProperty(b, Symbol.iterator, {
    enumerable: false,
    writable: false,
    configurable: true,
    value: function () {
        var me = this;
        var idx = 0;
        var keys = Object.keys(me);
        return {
            next: function () {
                return {
                    value: me[keys[idx++]],
                    done: (idx > keys.length)
                }
            }
        }
    }
});

for(var j of b){
    console.log(j);     // 結果依次是:arvin,30
}
// 下面的代碼相似上面的for...of...循環的內部實現
var c = b[Symbol.iterator]();
while(true){
  var newValue = c.next();
  if(newValue.done){
    break;
  }
  console.log(newValue.value)   // 結果依次是:arvin,30
}

代碼解讀:從上面的這個demo能夠看出,ES6的迭代器是實現要求必需要實現一個Symbol.iterator接口,而且該接口要返回一個帶有next方法的對象,並且該next方法必須包含至少兩個值,value以及done,前者是迭代器的輸出值,後者是判斷迭代終止條件。下面附上一個通用上傳迭代器的運用例子:this

Examplecode

let getUploadObj = {
    getActiveUploadObj (){
        try {
            return new ActiveXObject('TXFTNActiveX.FTNUpload');   // IE上傳控件
        } catch (e) {
            return false;
        }
    },
    getFalshUploadObj () {  
        try {
            new ActiveXObject('ShockwaveFlash.ShockwaveFlash');   // Flash上傳控件
            let str = '<object type="application/x-shockwave-flash"></object>';
            return $(str).appendTo($('body'));
        } catch (e) {
            return false;
        }
    },
    getFormUploadObj () {
        let str = '<input name="file" type="file" calss="ui-file"/>';   // 表單上傳
        return $(str).appendTo($('body'));
    }
}

// 給對象getUploadObj定義iterator接口,上面演示過這段代碼
// 這裏能夠經過工廠模式,抽象成一個專門給對象安裝iterator接口的函數,這樣就能夠省卻不少重複代碼了。
Object.defineProperty(getUploadObj, Symbol.iterator, {
    enumerable: false,
    writable: false,
    configurable: true,
    value: function(){
        var o = this;
        var idx = 0;
        var ks = Object.keys(o);
        return {
            next: function(){
                return {
                    value: o[ks[idx++]],
                    done: (idx > ks.length)
                }
            }
        }
    }
});


function iteratorUploadObj (uploadObj){
    // 直接使用`for...of`遍歷uploadObj對象
    for(let getUpload of uploadObj){
        let uploadObj = getUpload();
        if(uploadObj) return uploadObj;
    }
}

let uploadObj = iteratorUploadObj(getUploadObj);
console.log(uploadObj);  // [input, prevObject: Z.fn.init[1], context: undefined]
相關文章
相關標籤/搜索