细说JS循环方法

2,334 阅读3分钟

楔子

传统的JS循环方法,while,do while,for与其他语言类似,本文不做过多描述,更多的集中在:

  • 常见遍历方法for-in、for-of、entires、Object.keys、Object.getOwnProperty比较。
  • 数组遍历map、forEach、reduce、every、some、fiter方法的比较。

常见遍历方法

  • for-in:遍历数组索引、对象的属性,用于遍历可枚举属性,包括自有属性、继承自原型的属性

var obj = {"name":"sme","sex":"female"};
Object.defineProperty(obj, "age", {value:"18", enumerable:false});//增加不可枚举的属性age
Object.prototype.protoPer1 = function(){console.log("name is sme");};//通过原型链增加属性,为一个函数
for(var a in obj){
    console.log(a);
}
// 输出:name,sex,ProtoPer1
//注意:属性age为不可可枚举,所以没有输出。
  • for-of:允许遍历 Arrays(数组), Strings(字符串), Maps(映射), Sets(集合),Arguments Object(参数对象)等可迭代的数据结构,返回的是属性值,但不允许遍历对象

for (const value of strings) { 
  console.log(value);
}
  • forEach:遍历数组,调用数组的每个元素,并将元素传递给回调函数。

    不能使用break、continue和return语句 可改变原有数组
var arr = [1,2,3];
arr.forEach(
    function(value,index,arr){
        console.log(index)//索引
        console.log(value)//值
        //以下为错误代码
        //if(index/2 === 0){
           // continue;
        //}
    },this)
  • for-in和for-of和forEach比较

  1. for..of:适用遍历数/数组对象/字符串/map/set等拥有迭代器对象的集合.但是不能遍历对象,因为没有迭代器对象.
  2. 与forEach()不同的是,它可以正确响应break、continue和return语句
  3. for-of循环不支持普通对象,但如果你想迭代一个对象的属性,你可以用for-in循环或内建的Object.keys()方法。
  • Object.getOwnProperty:主要用于返回对象的自有属性,包括可枚举和不可枚举的属性,不包括继承自原型的属性。

var obj = {"name":"sme","sex":"female"};
Object.defineProperty(obj, "age", {value:"18", enumerable:false});//增加不可枚举的属性age
Object.prototype.protoPer1 = function(){console.log("name is sme");};//通过原型链增加属性,为一个函数
console.log(Object.getOwnPropertyNames(obj));
//输出:[name,sex,age]
//注意:返回的也是数组,原型上添加的属性不会被遍历到
  • Object.keys: 返回一个数组,元素均为对象自有可枚举的属性

var obj = {"name":"sme","sex":"female"};
Object.defineProperty(obj, "age", {value:"18", enumerable:false});//增加不可枚举的属性age
Object.prototype.protoPer1 = function(){console.log("name is sme");};//通过原型链增加属性,为一个函数
console.log(Object.keys(obj));
//输出:[name,sex]
//注意:原型上添加的属性不会被遍历到
  • Object.entries:返回二元数组,键值对

同上例子
console.log(Object.entries(obj))
\\输出[["name","sme"],["sex","female"]]
  • array.map(): 遍历数组,与forEach类,区别是不改变原数组,可以使用return返回结果,break,contiune不生效

var arr = [1,2,3]
var res = arr.map(function(val,index,arr){
    return val*2
})
//res=[2,4,6]
//arr=[1,2,3]
  • array.filter():遍历过滤数组
  • every():遍历数组是否全部满足,返回true
    array.every(function(currentValue,index,arr), thisValue)
  • some(): 遍历数组一个满足即为true
    array.some(function(currentValue,index,arr),thisValue)
  • array.reduce(function(total, currentValue, currentIndex, arr)):

    接收一个函数作为累加器,数组中的每个值(从左到右)开始缩减,最终计算为一个值。
var numbers = [65, 44, 12, 4];
function getSum(total, num) {
    return total + num;
}
function myFunction(item) {
    document.getElementById("demo").innerHTML = numbers.reduce(getSum);
}
//输出:125

总结

  1. forEach、map、filter、reduce、every、some 都会有 break 和 continue不生效的问题,因为是在function中,但function解决了闭包陷阱的问题; 要使用 break、continue 可以使用 for、for-in、for-of、while。
  2. for-of为ES6语法糖,尽量使用for-of;
  3. 用于循环对象属性使用:for-in