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
在可迭代对象(包括 Array,Map,Set,String,TypedArray,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。
- 支持数组,还支持大多数类数组对象,例如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 参数,或者赋值为 null 或 undefined,则 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语言规范:'forEachdoes 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); // undefined5 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 参数,或者赋值为 null 或 undefined,则 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。