JS for-in、for-of、forEach、map、filter各大循环区别讲解

在讲循环的之前,先知道一下循环结构的执行步骤 

  1、声明循环变量;
  2、判断循环条件;
  3、执行循环体操作;
  4、更新循环变量;
  5、然后循环执行2-4,直到条件不成立,跳出循环。

for-in循环

for-in 循环主要用于遍历对象(可以遍历数组)
格式: 

for (variable in object) {...}

  keys表示obj对象的每一个键值对的键!!所有循环中,需要使用obj[keys]来取到每一个值!!!
  for-in 循环,遍历时不仅能读取对象自身上面的成员属性,也能延续原型链遍历出对象的原型属性
  所以,可以使用hasOwnProperty判断一个属性是不是对象自身上的属性。
  obj.hasOwnProperty(keys)==true 表示这个属性是对象的成员属性,而不是原先属性

for..in 不应该被用来迭代一个下标顺序很重要的 Array .

数组索引仅是可枚举的整数名,其他方面和别的普通对象属性没有什么区别。for...in 并不能够保证返回的是按一定顺序的索引,但是它会返回所有可枚举属性,包括非整数名称的和继承的。因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。 因此当迭代那些访问次序重要的 arrays 时用整数索引去进行 for 循环 (或者使用 Array.prototype.forEach() 或 for...of 循环) 。

for...in循环缺点:
  ①数组的键名是数字,但是for...in循环是以字符串作为键名“0”、“1”、“2”等等。
  ②for...in循环不仅遍历数字键名,还会遍历手动添加的其他键,甚至包括原型链上的键。
  ③某些情况下,for...in循环会以任意顺序遍历键名。
  (for...in循环主要是为遍历对象而设计的,不适用于遍历数组。)

for-of循环 

ES6 新出的一种作为遍历所有数据结构的统一的方法。for...of循环可以使用的范围包括数组、Set 和 Map 结构、某些类似数组的对象(比如arguments对象、DOM NodeList 对象)、以及字符串。

详细数据结构的遍历参考:https://www.cnblogs.com/baiyunke/p/7821299.html
for...of循环优点:
  有着同for...in一样的简洁语法,但是没有for...in那些缺点。
  不同于forEach方法,它可以与break、continue和return配合使用。
  提供了遍历所有数据结构的统一操作接口。

总结来说 : for in总是得到对像的key或数组,字符串的下标,而for of和forEach一样,是直接得到值。

forEach循环 map循环

共同点:

    1.都是循环遍历数组中的每一项。

    2.forEach() 和 map() 里面每一次执行匿名函数都支持3个参数:数组中的当前项item,当前项的索引index,原始数组input。

    3.匿名函数中的this都是指Window。

    4.只能遍历数组

区别:

1.forEach()   没有返回值

arr[].forEach(function(value,index,array){
  //do something
})
  • 参数:value数组中的当前项, index当前项的索引, array原始数组;
  • 数组中有几项,那么传递进去的匿名回调函数就需要执行几次;
  • 理论上这个方法是没有返回值的,仅仅是遍历数组中的每一项,不对原来数组进行修改;但是可以自己通过数组的索引来修改原来的数组
let arr = [12, 23, 34, 45, 56];
let res = arr.forEach(function (item, index, array) {
    array[index] = item * 10;
})
console.log(res); // undefined;  
console.log(arr); // Array(5) 0: 120 1: 230 2: 340 3: 450 4: 560

2.map()    有返回值,可以return 出来。

arr[].map(function(value,index,array){
  //do something
  return XXX
})
  • 参数:value数组中的当前项,index当前项的索引,array原始数组;
  • 区别:map的回调函数中支持return返回值;return的是一个新数组,并不影响原来传入的数组(只是把原数组克隆一份,把克隆的数组中对应项改变了当成新数组返回);
let ary = [2, 30, 4, 42, 1];
let ans = ary.map(function (item, index, array) {
    return item * 10;
})
console.log('map:',ans); // [20, 300, 40, 420, 10];  返回的新数组把原数组拷贝了一份进行了修改
console.log('map:',ary); // [2, 30, 4, 42, 1];  原数组并未发生变化

注意:不管是forEach还是map在IE6-8下都不兼容(不兼容的情况下在Array.prototype上没有这两个方法)

封装一个都兼容的方法:

// forEach遍历数组 callback [function] 回调函数 context [object] 上下文   
Array.prototype.myForEach = function myForEach(callback,context){  
    context = context || window;  
    if('forEach' in Array.prototye) {  
        this.forEach(callback,context);  
        return;  
    }  
    //IE6-8下自己编写回调函数执行的逻辑  
    for(var i = 0,len = this.length; i < len;i++) {  
        callback && callback.call(context,this[i],i,this);  
    }  
}  
//map遍历数组 callback [function] 回调函数 context [object] 上下文 
Array.prototype.myMap = function myMap(callback,context){  
    context = context || window;  
    if('map' in Array.prototye) {  
        return this.map(callback,context);  
    }  
    //IE6-8下自己编写回调函数执行的逻辑  
    var newAry = [];  
    for(var i = 0,len = this.length; i < len;i++) {  
        if(typeof  callback === 'function') {  
            var val = callback.call(context,this[i],i,this);  
            newAry[newAry.length] = val;  
        }  
    }  
    return newAry;  
}  

filter()过滤循环

filter方法用于过滤数组成员,满足条件的成员组成一个新数组返回。它的参数是一个函数,所有数组成员依次执行该函数,返回结果为true的成员组成一个新数组返回。该方法不会改变原数组。filter循环有返回值

let res = [1, 2, 3, 4, 5].filter(function (elem) {
    return (elem > 3);
}) 
console.log('filter:',res); // [4, 5] 
// 上面代码将大于3的数组成员,作为一个新数组返回。

var arr = [0, 1, 2, 'a', true, false];
let rey = arr.filter(Boolean)
console.log('filter:',arr); // [0, 1, 2, "a", true, false]
console.log('filter:',rey); // [1, 2, "a", true]
//过滤出值为真的

filter方法一个参数的函数 参数:value数组中的当前项,index当前项的索引,array原始数组;


[1, 2, 3, 4, 5].filter(function (elem, index, arr) { 
    return index % 2 === 0; 
}); 
// [1, 3, 5]

filter方法也可以接受第二个参数,用来绑定参数函数内部的this变量。

var obj = {
    MAX: 3
};
var myFilter = function (item) {
  if (item > this.MAX) return true;
};
var arr = [2, 8, 3, 4, 1, 3, 2, 9];
var rey = arr.filter(myFilter, obj);
console.log('filter:',rey);//[8, 4, 9]

过滤器myFilter内部有this变量,它可以被filter方法的第二个参数obj绑定,返回大于3的成员。

以上循环特征(相同与不同):

一:map(),foreach,filter循环的共同之处:

      1.foreach,map,filter循环中途是无法停止的,总是会将所有成员遍历完。

      2.他们都可以接受第二个参数,用来绑定回调函数内部的this变量,将回调函数内部的this对象,指向第二个参数,间接操作这个参数(一般是数组)。

二:map、forEach和filter循环都会跳过空位,for和while不会

var f = function (n) { 
    return 'a' 
}; 
 
[1, undefined, 2].map(f) // ["a", "a", "a"] 
[1, null, 2].map(f) // ["a", "a", "a"]
[1, , 2].map(f) // ["a", , "a"]

上面代码中,map方法不会跳过undefined和null,但是会跳过空位。

更详细的介绍请参考:https://blog.csdn.net/qq_41899174/article/details/82797089

你可能感兴趣的:(JS for-in、for-of、forEach、map、filter各大循环区别讲解)