zoukankan      html  css  js  c++  java
  • 实例解析forEach、for...in与for...of

    在开发过程中经常需要循环遍历数组或者对象,js也为我们提供了不少方法供使用,其中就有三兄弟forEach、for...in、for...of,这三个方法应该是使用频率最高的,但很多人却一值傻傻分不清,经常该混淆了它们的功能和注意点。就在今天,我来给它们一个大区分(*・ω< )。

    forEach

    forEach() 方法对数组的每个元素执行一次提供的函数。

    从ES5开始,Javascript内置了forEach方法,用来遍历数组 。

    var arr = ['a', 'b', 'c', 'd', 'e'];
     
    arr.forEach(function(item) {
      console.log(item); // a,b,c,d,e
    });

    !注意:forEach方法没办法使用 break 语句跳出循环,或者使用return从函数体内返回。

    for...in

    for...in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性,语句都会被执行。

    语法:

    for (variable in object) {...}

    variable 在每次迭代时,将不同的属性名分配给变量。

    object 被迭代枚举其属性的对象。

    // 例子一
    let obj = {a: '1', b: '2', c: '3', d: '4'};
    for (let o in obj) {
        console.log(o)    // 遍历的实际上是对象的属性名称 a,b,c,d
        console.log(obj[o])  // 这个才是属性对应的值1,2,3,4
    }
     
     
    // 例子二
    Object.prototype.objName = 'objName '; 
    var obj = {a: '1', b: '2', c: '3', d: '4'};
    for (let o in obj) {
        console.log(o)    // a,b,c,d,objName 
    }

    for...in 循环只遍历可枚举属性。像 Array和 Object使用内置构造函数所创建的对象都会继承自Object.prototype和String.prototype的不可枚举属性,例如 String 的 indexOf()  方法或 Object的toString()方法。循环将遍历对象本身的所有可枚举属性,以及对象从其构造函数原型中继承的属性(更接近原型链中对象的属性覆盖原型属性)。 

    ! 注意:建议不使用for...in去迭代一个Array。因为设计之初,是给普通以字符串的值为key的对象使用的,而非数组。

    数组索引只是具有整数名称的枚举属性,并且与通用对象属性相同。使用不能保证for...in将以任何特定的顺序返回索引。因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。因此当迭代访问顺序很重要的数组时,最好用整数索引去进行for循环(或者使用 Array.prototype.forEach() 或 for...of 循环)。

    对于for...in的循环,可以由break,throw终止。

    var obj = {a: '1', b: '2', c: '3', d: '4'}
    for (let o in obj) {
        if(o=='c'){
            break;
        }
        console.log(o);
    }
     
    // 输出: a,b

    for...of

    for...of 语句在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。

    语法:

    for (variable of iterable) {
      //statements
    }

    variable 在每次迭代中,将不同属性的值分配给变量。

    iterable 被迭代枚举其属性的对象。

    迭代数组Array

    let iterable = [10, 20, 30];
    for (let value of iterable) {
      console.log(value);
    }
    // 10
    // 20
    // 30

    迭代字符串String

    let iterable = "boo";
    for (let value of iterable) {
      console.log(value);
    }
    // "b"
    // "o"
    // "o"

    迭代Map

    let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);
     
    for (let entry of iterable) {
      console.log(entry);
    }
    // ["a", 1]
    // ["b", 2]
    // ["c", 3]
     
    for (let [key, value] of iterable) {
      console.log(value);
    }
    // 1
    // 2
    // 3

    迭代Set

    let iterable = new Set([1, 1, 2, 2, 3, 3]);
     
    for (let value of iterable) {
      console.log(value);
    }
    // 1
    // 2
    // 3

    对于for...of的循环,可以由breakthrow 或return终止。在这些情况下,迭代器关闭

    function* foo(){ 
      yield 1; 
      yield 2; 
      yield 3; 
    }; 
     
    for (let o of foo()) { 
      console.log(o); 
      break; // closes iterator, triggers return
    }

    for...of与for...in的区别 

    无论是for...in还是for...of语句都是迭代一些东西。它们之间的主要区别在于它们的迭代方式。

    for...in 语句以原始插入顺序迭代对象的可枚举属性。

    for...of 语句遍历可迭代对象定义要迭代的数据。

    以下示例显示了与Array一起使用时,for...of循环和for...in循环之间的区别。

    Object.prototype.objCustom = function() {}; 
    Array.prototype.arrCustom = function() {};
     
     
    // 每个对象将继承objCustom属性,并且作为Array的每个对象将继承arrCustom属性,
    // 因为将这些属性添加到Object.prototype和Array.prototype。
    // 由于继承和原型链,对象iterable继承属性objCustom和arrCustom。
    let iterable = [3, 5, 7];
    iterable.foo = 'hello world';
     
     
    // 此循环仅以原始插入顺序记录iterable对象的可枚举属性。
    // 它不记录数组元素3, 5, 7 或hello,因为这些不是枚举属性。 
    // 但是它记录了数组索引以及arrCustom和objCustom。
    // 前面说了,不建议使用for...in迭代数组,这里是纯粹举例才这样写,请勿模仿
    for (let i in iterable) {
      console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom"
    }
     
     
    // 这个循环类似于第一个,但是它使用hasOwnProperty() 来检查,
    // 如果找到的枚举属性是对象自己的(不是继承的)。如果是,该属性被记录。
    // 记录的属性是0, 1, 2和foo,因为它们是自身的属性(不是继承的)。
    // 属性arrCustom和objCustom不会被记录,因为它们是继承的。
    for (let i in iterable) {
      if (iterable.hasOwnProperty(i)) {
        console.log(i); // 0, 1, 2, "foo"
      }
    }
     
     
    // 该循环迭代并记录iterable作为可迭代对象定义的迭代值,这些是数组元素 3, 5, 7,而不是任何对象的属性。
    for (let i of iterable) {
      console.log(i); // 3, 5, 7
    }

    在上面可以粗略看到,for...in循环的是对象的键(key),而for...of则是对象的值。

    除此之外,for...of 不能循环非iterable对象。

    let newObj = {a: '1', b: '2', c: '3', d: '4'};
    for (let o of newObj) {
        console.log(o);    // Uncaught TypeError: newObj is not iterable
    }
  • 相关阅读:
    1061. 判断题(15)
    1031. 查验身份证(15)
    1006. 换个格式输出整数 (15)
    1046. 划拳(15)
    1001. 害死人不偿命的(3n+1)猜想 (15)
    1021. 个位数统计 (15)
    1054. 求平均值 (20)
    写出这个数 (20)
    设计模式之中介者模式
    kill命令
  • 原文地址:https://www.cnblogs.com/slly/p/10579900.html
Copyright © 2011-2022 走看看