对象遍历

1,383 阅读5分钟

1 for 循环

  • 普通for循环,经常用的数组遍历
var arr = [1,2,3,4,5];
 for ( var i = 0; i <arr.length; i++){
    console.log(arr[i]);
}
  • 优化版for循环:使用变量,将长度缓存起来,避免重复获取长度,数组很大时优化效果明显
for(var j = 0,len = arr.length; j < len; j++){
    console.log(arr[j]);
}


2 for...of

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

  • 支持数组,还支持大多数类数组对象,例如DOM NodeList对象。  
  • 也支持字符串遍历。
  • 可以由break, throw continue return终止。
  • 避开了for-in循环的所有缺陷
  • 性能要好于forin,但仍然比不上普通for循环


3 for...in

  • for-in是为遍历对象而设计的,不适用于遍历数组。
  • 用来循环对象的所有属性,其实准确的来说,是循环对象的可枚举属性; 
  • 可以访问到对象原型链上的数据; 
  • 遍历数组的缺点:数组的下标index值是数字,for-in遍历的index值"0","1","2"等是字符串。
  • 效率最低。
  • 不推荐使用(for…in)来遍历数组,因为这种枚举不仅会包含所有数值索引还会包含所有可枚举属性,在某些情况下,可能按照随机顺序遍历数组元素。


4 forEach

对数组的每个元素执行一次提供的函数。

ES5推出的,数组自带的循环,主要功能是遍历数组,实际性能比for还差。

arr.forEach(function(currentValue, currentIndex, array){
    
})

4.1 参数说明

callback:为数组中每个元素执行的函数,该函数接收三个参数:
    • currentValue:数组中正在处理的当前元素。
    • currentIndex:可选,数组中正在处理的当前元素的索引。
    • array:可选,forEach() 方法正在操作的数组。
thisArg:可选。当执行回调函数时用作 this 的值(参考对象)。

如果 thisArg 参数有值,则每次 callback 函数被调用的时候,this 都会指向 thisArg参数上的这个对象。如果省略了 thisArg 参数,或者赋值为 nullundefined,则 this 指向全局对象。

4.2 返回值

undefined

4.3 说明

  • forEach 方法按升序为数组中含有效值的每一项执行一次callback 函数,那些已删除或者未初始化的项将被跳过(例如在稀疏数组上)。

[1,2,,5,].forEach(function(currentValue, currentIndex, array){
    console.log(currentValue + ' - ' + currentIndex + ' - ' + array);
})
输出:
1 - 0 - 1,2,,5
2 - 1 - 1,2,,5
5 - 3 - 1,2,,5
  • 不能使用break语句中断循环,也不能使用return语句返回到外层函数。
  • forEach() 被调用时,不会改变原数组(即调用它的数组),即使传递的参数里的 callback被调用时可能会改变原数组。(译注:此处说法似不够准确,可参考EMCA语言规范:'forEach does not directly mutate the object on which it is called but the object may be mutated by the calls to callbackfn.',即forEach不直接改变调用它的对象,但是对象可能会被callback改变。)

即:理论上这个方法是没有返回值的,仅仅是遍历数组中的每一项,不对原来数组进行修改;但是可以自己通过数组的索引来修改原来的数组。

例:

var arr = [1, 2, 3, 4];arr.forEach(function(value) {  value++;});console.log(arr); // [1, 2, 3, 4]
var arr = [1, 2, 3, 4];const result = arr.forEach(function(value, index) {  arr[index] = value * 10;});console.log(arr); // [10, 20, 30, 40]console.log(result); // undefined


5 map

创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。

var arr = [1, 2, 3, 4];

const mapResult = arr.map(x => x * 2);

console.log(mapResult); // [2,4,6,8]
console.log(arr); // [1,2,3,4]

5.1 参数说明

callback:为数组中每个元素执行的函数,该函数接收三个参数:
  • currentValue:数组中正在处理的当前元素。
  • currentIndex:可选,数组中正在处理的当前元素的索引。
  • array:可选,forEach() 方法正在操作的数组。
thisArg:可选。当执行回调函数时用作 this 的值(参考对象)。

如果 thisArg 参数有值,则每次 callback 函数被调用的时候,this 都会指向 thisArg参数上的这个对象。如果省略了 thisArg 参数,或者赋值为 nullundefined,则 this 指向全局对象。

5.2 返回值

一个新数组,每个元素都是回调函数的结果。

5.3 说明

map 不修改调用它的原数组本身(当然可以在 callback 执行时改变原数组)。

var arr = [1, 2, 3, 4];
const result = arr.map(function(value, index) {
  arr[index] = value * 10;
  return value * 10;
});
console.log(arr); // [10, 20, 30, 40]
console.log(result); // [10, 20, 30, 40]

通常情况下,map 方法中的 callback 函数只需要接受一个参数,就是正在被遍历的数组元素本身。但这并不意味着 map 只给 callback 传了一个参数。这个思维惯性可能会让我们犯一个很容易犯的错误。

// 下面的语句返回什么呢:
["1", "2", "3"].map(parseInt);
// 你可能觉的会是[1, 2, 3]
// 但实际的结果是 [1, NaN, NaN]

// 通常使用parseInt时,只需要传递一个参数.
// 但实际上,parseInt可以有两个参数.第二个参数是进制数.
// 可以通过语句"alert(parseInt.length)===2"来验证.
// map方法在调用callback函数时,会给它传递三个参数:当前正在遍历的元素, 元素索引, 原数组本身.
// 第三个参数parseInt会忽视, 但第二个参数不会,也就是说,
// parseInt把传过来的索引值当成进制数来使用.从而返回了NaN.

function returnInt(element) {
  return parseInt(element, 10);
}

['1', '2', '3'].map(returnInt); // [1, 2, 3]
// 意料之中的结果

// 也可以使用简单的箭头函数,结果同上
['1', '2', '3'].map( str => parseInt(str) );

// 一个更简单的方式:
['1', '2', '3'].map(Number); // [1, 2, 3]
// 与`parseInt` 不同,下面的结果会返回浮点数或指数:
['1.1', '2.2e2', '3e300'].map(Number); // [1.1, 220, 3e+300]
  • 实际效率还比不上foreach。