2016-08-13 91 views
0

過去幾個月我一直在玩JavaScript,發現它在多年不使用之後真的很爽快。什麼是最簡潔的方式來轉換JavaScript「幾乎數組」到「數組」?

也就是說,有一點特別令我困擾的是它的'如何描述的不一致'[]「構造。

特別是,我習慣了讓數組擁有一個「地圖」功能,但很多東西都是「[]」 - 不支持地圖,但通常支持同義詞,有時根本不支持。

例子:

  1. 的document.getElementById( '我-DIV')兒童

擁有所有我每一個需要映射在它的時間沒有mappability和,我不得不求助於for循環。

  • document.querySelectorAll( '#我-DIV *')
  • 具有forEach :: callback -> undefined

    不同於地圖,不返回一個數組,所以鏈接變換被「奇怪」,因爲除了映射到對象之外,還必須將結果存儲在數組中以繼續。

    這意味着以下不起作用。

    (() => { 
        document.querySelectorAll('#my-div *').forEach((divObject) => { 
         console.log('found a ' + divObject.tagName + '.'); 
         return divObject; 
        }).forEach((divObject) => { 
         console.log('more transformations on ' + divObject.tagName + '.'); 
         return divObject; 
        }); 
    })(); 
    

    但這種意願:

    (() => { 
        var children = []; 
    
        document.querySelectorAll('#my-div *').forEach((divObject) => { 
         children.push(divObject); 
        }); 
    
        children.map((divObject) => { 
         console.log('found a ' + divObject.tagName + '.'); 
         return divObject; 
        }).map((divObject) => { 
         console.log('more transformations on ' + divObject.tagName + '.'); 
         return divObject; 
        }); 
    })(); 
    

    但元素「一一」複製一個foreach裏面是沒有實際意義的,一般發佈的代碼之前,必須優化掉只是額外的工作像這樣,因爲這對於沒有充分理由的表現是不利的。

    1. jQuery的地圖工作正常。例如$('#my-div *')map :: callback -> array that supports map operation。所以它可以按預期鏈接。

    問題

    有沒有克服的不是陣列具有類似的接口(似乎是「陣列」,但不支持Array.prototype.map的東西)的inconsistancy一個更清潔的方式使用for循環執行第一次迭代,只有在知道其行爲與您認爲它的行爲方式後,纔會推送內容?

    +1

    'var properArray = [... arrayLike]'或'var properArray = Array.from(arrayish)' – Redu

    +0

    這似乎比手動逐一複製效率更高。我所要做的只是'Array.from(document.querySelectorAll('#checkboxes [type =「checkbox」]'))'現在我可以映射^ _ ^。你可以自己做出答案,我可以接受嗎? – Dmitry

    +0

    @Dmitry就「效率」而言,沒有多少區別; Redu提到的那兩種方法也將執行逐元轉移。 – Pointy

    回答

    1

    對於所有的異國陣列狀的節點列表等,如果他們是可迭代的,你可以放心地做這樣

    var properArray = [...arrayLike]var properArray = Array.from(arrayish)

    或者你甚至可以像

    var properarray = Array(arrayish.length), 
           i = 0; 
    for (var key of arrayish) while i < arrayish.length properArray[i++] = arrayish(key); 
    

    如果你有一個對象像

    var o = {prop_1:"one thing", 
     
         prop_2:"another thing"}, 
     
        a = []; 
     
    
     
    o[Symbol.iterator] = function*(){ 
     
             var oks = Object.keys(this); 
     
             for (var key of oks) yield this[key] 
     
            } 
     
    a = [...o]; 
     
    console.log(a);

    你可以使它迭代並以相同的方式將其轉換爲數組;

    1

    你能避免使用.apply形成陣列的複製:(顯然調用.map()本身將作出新的陣列,但會發生什麼反正)

    var nodeList = document.getElementsByTagName("p"); 
    
    Array.prototype.map.apply(nodeList, function(node) { 
        // do something with node 
    }); 
    

    +0

    是的,我可以理解它將會創建一個新的數組,無論由於地圖的本質,這是返回一些你可以繼續映射到,這需要一個新的數組。但能夠做到這一點很好。 – Dmitry

    +0

    如果您不想映射陣列,請使用'forEach'。 – Oriol

    0

    我建議是:避免鏈接

    轉換爲陣列和映射只是爲了能鏈forEach是浪費。

    而是將NodeList存儲在一個變量中。

    var nodes = document.querySelectorAll('*'); 
     
    nodes.forEach(node => 
     
        console.log('found a ' + node.tagName + '.')) 
     
    nodes.forEach(node => 
     
        console.log('more transformations on ' + node.tagName + '.'));

    注意節點列表不是可迭代直到DOM4。

    相關問題