JS常用循环遍历的方法

221 阅读5分钟

前言:在js里面,处理引用类型循环遍历的方法基本上都是针对于“对象”和“数组”,接下来我们就来看下各种循环遍历方法之间的用法及差别。

一:对象

1. for...in

该方法 除了遍历自身还会遍历 “原型链” 上的可枚举属性。所以,当只需要遍历自身的时候,性能上会受一定的影响,当不需要遍历原型上的属性时,一般我们会通过hasOwnProperty进行判断,将原型上的属性给过滤掉。

let person = Object.create({
    six: '男'
});
person.age = '18';
person.name = 'voledy';
for(let i in person){
    if(person.hasOwnProperty(i)){
        console.log(person[i])   // { age: 18, name: 'voldy'}
    }
}

2. Object.key(obj) 和 Object.values(obj)

上述两个方法根据"keys" 和 "values"就知道遍历的是“属性名” 和 “属性值”。返回的是一个数组。该两个方法只会遍历自身(不含继承的)所有可枚举属性名/值。

let person = {
    name: 'voledy',
    age: 18
};
console.log(Object.keys(person))   // ["name", "age"]
console.log(Object.values(person))  // ["voledy", 18]

3.Object.getOwnPropertyNames(obj)

和Object.keys(obj)类似,该方法返回的是一个数组,只会遍历自身(不含继承的)所有属性名。但是它们的主要差别就是该方法会将不可枚举的属性也遍历出来

// Object.defineProperty(obj, prop, descriptor) 该方法可以设置对象的属性,功能还是蛮强大的。后期我会专门写一篇文章来介绍该方法。
let person = {
    name: 'voledy',
    age: 18
};
Object.defineProperty(person,'age',{
    enumerable: false
});
console.log(Object.keys(person))  //["name"]
console.log(Object.getOwnPropertyNames(person))  //["name", "age"]

4.Object.getOwnPropertySymbols(obj)

该方法和其他的遍历方法有点不太一样,但是返回的仍是数组。该方法主要是遍历以Symbol作为key值的属性。如果对象中不存在Symble属性,返回的是空数组,不包括原型链上的属性。

let person1 = {
    name: 'voledy',
    age: 18
};
console.log(Object.getOwnPropertySymbols(person1)) //  []

let person2 = Object.create({
    [Symbol('address')]: '广东省深圳市',
})
person2.name = 'voledy';
person2.age = 18;
person2[Symbol('from')] = '深圳';
person2[Symbol('to')] = '上海';
console.log(Object.getOwnPropertySymbols(person2))  // [Symbol(from), Symbol(to)]

5.Reflect.ownKeys(obj)

会存在这么一种情况,假如定义的对象中有Symbol属性,但是又想遍历对象中全部的属性,那该咋办呢?该方法可以帮助你。返回的仍是数组,包括不可枚举的属性和 Symbol 属性。但是不包括原型链上的属性。

let person = Object.create({
    [Symbol('address')]: '深圳市南山区',
})
person.name = 'voledy';
person.age = 18;
person[Symbol('from')] = '深圳';
person[Symbol('to')] = '上海';

console.log(Reflect.ownKeys(person))  // ["name", "age", Symbol(from), Symbol(to)]

二:数组

1.for

该方法是最简单的一种遍历循环方法,用的频率相对较高。可优化,可修改循环语句,中途可以break, 直接跳出循环。

//建议使用临时变量,将长度缓存起来,避免重复获取数组长度。当数据量大时,性能较为明显。
let num = [1, 2, 3, 4, 5, 6]
for(let i = 0, len = num.length; i < len; i++){
    if(num[i] > 2){
        console.log(num[i])   // 3  
        break;  
    }
}
//当有break时,直接打印出 3  没有break时,打印的结果为 3 4 5 6

2.forEach(function(currentValue, index, arr), thisValue)

该方法调用数组中的每一个元素,并将元素传递给回调函数。该方法没有返回值。
currentValue: 必填,当前元素。
index: 选填,当前元素的索引
arr: 选填, 所属的数组对象
thisValue: 选填[比较少用], 传递给函数的值一般用this值,如果该参数为空,"undefined"会传递给"this"值。

let num = [1, 2, 3, 4, 5, 6]
num.forEach(val =>{
    if(val > 4){
        console.log(val)  // 5 6
    }
})

3.map(function(currentValue, index, arr), thisValue)

该方法 有返回值。返回一个新的数组,不会改变原始数组。参数和forEach一直,最大的不同就是“forEach没有返回值”,“map有返回值”

let num = [1, 2, 3, 4, 5, 6]
let num2 = num.map(val =>{
    return val * 2
})
console.log(num2)  //[2, 4, 6, 8, 10, 12]

4.filter(function(currentValue, indedx, arr), thisValue)

该方法主要是对数组的过滤。有返回值,返回一个新的数组,不会改变原始数组。

let num = [1, 2, 3, 4, 5, 6]
let num2 = num.filter(val =>{
    return val > 2
})
console.log(num2)  // [3, 4, 5, 6]

5.some(function(currentValue,index,arr),thisValue)

该方法主要是检测数组中的元素是否满足条件。执行该方法会一直在找符合条件的值,一旦找到,则不会继续迭代下去。简单的说就是:只要有一个元素满足条件,则会立即返回true,剩余的元素不会再检测了。没有满足条件的则返回false.

let num = [1, 2, 3, 4, 5, 6, '10']
let num2 = num.some(val =>{
    return val > 2
})
console.log(num2) // true

6.every(function(currentValue,index,arr),thisValue)

该方法主要是检测数组中所有的元素是否满足条件。一旦有一个不符合条件,则不会继续迭代下去。简单的说就是:数组中所有的元素满足条件才会返回true,只要有一个不满足条件即返回false,剩余的元素不会再检测了。

let num = [1, 2, 3, 4, 5, 6, '10']
let num2 = num.every(val =>{
    return val > 2
})
console.log(num2) // false
注:every方法和some方法有点类似,它们的区别是:数组中所有的元素满足条件,every才会返回true。数组中只要有
一个满足条件,则返回true

7.reduce(function(total, currentValue, currentIndex, arr), initialValue)

total:初始值/计算结束后的返回值
currentValue:当前元素
currentIndex:索引
arr:当前元素所属的数组对象
initialValue:传递给函数的初始值
该方法为数组中的每一个元素依次执行回调函数,功能比较强大,是一个高阶函数,有兴趣的可以专门去研究下这个方法。

let num = [1, 2, 3, 4, 5]
let num2 = num.reduce((val,tt) =>{
    return val + tt
})
console.log(num2) // 15
//该方法远远不止加,减,乘,除这么简单,还有很多"好玩"的技巧。比如:数组去重,求最大值最小值,函数维度转换等。

数组去重:
let num = [1, 2, 3, 3, 4, 5, 5, 6, 7, 7, 7]
let num2 = num.reduce((per,cur) =>{
    if(!per.includes(cur)){ 
        return per.concat(cur)
    }else{
        return per
    }
},[])
console.log(num2) // [1, 2, 3, 4, 5, 6, 7]

8.find(function(currentValue, index, arr),thisValue)

该方法返回符合条件的第一个元素,只有有符合条件的则立即返回,之后的元素不再执行,当没有符合条件的元素则返回 undefined。

let num = [
    {city: '北京', age: '18'},
    {city: '上海', age: '20'},
    {city: '广州', age: '25'},
    {city: '深圳', age: '18'},
]
let num2 = num.find((val,index) =>{
    return val.age === '18'
})
console.log(num2) // {city: "北京", age: "18"}

9.findIndex(function(currentValue, index, arr),thisValue)

该方法反回符合条件元素的位置,如果找不到符合条件元素则返回-1。 find()方法是返回符合条件的目标元素 findIndex()则是返回符合条件的目标元素位置。

let num = [
    {city: '北京', age: '18'},
    {city: '上海', age: '20'},
    {city: '广州', age: '25'},
    {city: '深圳', age: '18'},
]
let num2 = num.findIndex((val,index) =>{
    return val.age === '20'
})
console.log(num2) // 1