zoukankan      html  css  js  c++  java
  • forEach、for...in、for...of

    forEach

       数组实例的遍历方法

    const arr=['red', 'green', 'blue'];
    arr.forEach(function(element, index) {
        console.log(element);// red green blue
        console.log(index);// 0 1 2
    });

      forEach这种写法的问题是,无法中途跳出forEach循环,break命令或return命令都不能奏效。

    for...in

       JavaScript原有的循环,只能获得对象的键名,不能直接获取键值。

    var arr = ['a', 'b', 'c', 'd', 'e'];
    for(let i in arr) {
        console.log(i);//0 1 2 3 4
    }
    for(let index in arr) {
    console.log(arr[index]);// a b c d e
    }
    let es6 = {
        edition: 6,
        committee: "TC-39",
        standard: "ECMA-262"
    };
    for(let e in es6) {
        console.log(e);
    }
    //edition
    //committee
    //standard

      for...in循环有几个缺点:

        数组键名是数字,但是for...in循环是以字符串作为键名"0","1","2"等

        for...in循环不仅遍历数字键名,还会遍历手动添加的其它键,甚至包括原型链上的键。

        某些情况下,for...in循环会以任意顺序遍历键名。

      总之,for...in循环主要是为遍历对象为设计的,不适用于遍历数组。

    for...of

      ES6借鉴C++、Java、C#和Python语言,引入了for...of循环,作为遍历所有数据结构的统一的方法。一个数据结构只要部署了Symbol.iterator属性,就被视为具有iterator接口,就可以用for...of循环遍历它的成员。也就是说,for...of循环内部调用的是数据结构的Symbol.iterator方法。for...of循环可以使用的范围包括数组、Set和Map结构、某些类似数组的对象(比如arguments对象、DOM NodeList对象)、Generator对象以及字符串。

      数组原生具有iterator接口(即默认部署了Symbol.iterator属性),for...of循环本质上就是调用这个接口产生的遍历器,允许遍历获得键值

    var arr = ['a', 'b', 'c', 'd', 'e'];
    for(let i of arr) {
        console.log(i);//a b c d e
    }

      for...of循环可以代替数组实例的forEach方法

      for...of循环调用遍历器接口,数组的遍历器接口只返回具有数字索引的属性;这一点与for...in也不一样。

    let arr = [1,3,5];
    arr.foo = 'hello';
    for(let i in arr) {
        console.log(i);//'1', '3', '5', 'foo'
    }
    
    for(let i of arr) {
        console.log(i);//'1', '3', '5'
    }

      Set和Map结构也原生具有Iterator接口,可以直接使用for...of循环

    var engines = new Set(["Gecko", "Trident", "Webkit", "Webkit"]);
    for(var e of engines) {
        console.log(e);
    }
    //Gecko
    //Trident
    //Webkit
    var es6 = new Map();
    es6.set("edition", 6);
    es6.set("committee", "TC39");
    es6.set("standard", "ECMA-262");
    for(var [name, value] of es6) {
        console.log(name+ ":" + value);
    }
    //edition: 6
    //committee: TC39
    //standard: ECMA-262

      Set和Map遍历的顺序是按照各个成员被添加进数据结构的先后顺序。其次,Set结构遍历,返回的是一个值。Map结构遍历返回的是一个数组,该数组的两个成员分别为当前Map成员的键名和键值。

      for...of循环,获得数组的索引,可以借助数组实例的entries方法和keys方法。

    let arr = ["a", "b", "c"];
    for(let pair of arr.entries()) {
        console.log(pair);
    }
    //[0, 'a']
    //[1, 'b']
    //[2, 'c']

      for...of遍历类似数组的对象(String、DOM NodeList、arguments)

    //字符串
    let str="hello";
    for(let s of str) {
        console.log(s);// h e l l o
    }
    //DOM NodeList对象
    let paras = document.querySelectorAll("p");
    for(let p of paras) {
        p.classList.add("test");  
    }
    //arguments对象
    function printArgs() {
        for(let x of arguments) {
            console.log(x);
        } 
    }
    printArgs('a', 'b');
    //'a'
    //'b'

      对字符串来说,for...of循环还能够正确识别32位UTF-16字符

    for (let x of 'auD83DuDC0A) {
        console.log(x);
    }
    //'a'
    //'uD83DuDC0A'

      并不是所有类似数组的对象都具有Iterator接口,一个方法是用Array.from方法将其转换为数组

    let  arrayLike = [length: 2, 0: 'a', 1: 'b'];
    for(let x of array.from(arrayLike)) {
        console.log(x);
    }

      对于普通的对象,for...of结构不能直接使用,必须部署Iterator接口后才能使用。一种解决方法是将对象的键名生成一个数组,然后遍历这个数组:

    for(let key of Object.keys(someObject)) {
        console.log(key + ":" + someObject[key]);
    }

      另一个方法是使用Generator函数

    function* entries(obj) {
        for(let key of Object.keys(obj)) {
            yield [key, obj[key]];
        }
    }
    for(let [key, value] of entries(obj)) {
        console.log(key, '->', value);
    }
    //a -> 1
    //b -> 2
    //c -> 3

      for...of相对其它遍历方法,有以下优点:

        有着同for...in一样简洁的语法,但是没有for...in那些缺点;

        不同于forEach方法,它可以与break、continue和return配合使用

        提供了遍历所有数据结构的统一操作接口

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

    参考:

    Iterator和for...of

  • 相关阅读:
    CS academy Binary Flips(dp)
    [POJ 1637] Sightseeing tour(网络流)
    Codeforces 346D Robot Control(01BFS)
    BZOJ 2069: [POI2004]ZAW(Dijkstra + 二进制拆分)
    驱动之SPI,UART,I2C的介绍与应用20170118
    USB驱动之CDC类的介绍与应用20160905
    uCOS-II之移植20160823
    java之面向对象20160818
    Java之基础20160806
    Android之框架20160721
  • 原文地址:https://www.cnblogs.com/princess-knight/p/9326458.html
Copyright © 2011-2022 走看看