2016-08-13 92 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。

    相关问题