概念区别
- 循环(loop),指的是在满足条件的情况下,重复执行同一段代码。比如,while语句。(循环能对应集合,列表,数组等,也能对执行代码进行操作。)
- 迭代(iterate),指的是按照某种顺序逐个访问列表中的每一项。比如,for语句。(迭代只能对应集合,列表,数组等。不能对执行代码进行迭代。)
- 遍历(traversal),指的是按照一定的规则访问树形结构中的每个节点,而且每个节点都只访问一次。(遍历同迭代一样,也不能对执行代码进行遍历。)
- 递归(recursion),指的是一个函数不断调用自身的行为。比如,以编程方式输出著名的斐波纳契数列。
1.for...in 语句
for...in 语句以任意顺序遍历一个对象的可枚举属性。循环将迭代对象的所有可枚举属性和从它的构造函数的 prototype 继承而来的(包括被覆盖的内建属性)。
数组索引仅是可枚举的整数名,其他方面和别的普通对象属性没有什么区别。for...in 并不能够保证返回的是按一定顺序的索引,但是它会返回所有可枚举属性,包括非整数名称的和继承的。
因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。 因此当迭代那些访问次序重要的 arrays 时用整数索引去进行 for 循环 (或者使用 Array.prototype.forEach() 或 for...of 循环) 。
如果仅迭代自身的属性,而不是它的原型,那么使用 getOwnPropertyNames() 或执行 hasOwnProperty() 来确定某属性是否是对象本身的属性 (也能使用propertyIsEnumerable)。另外,如果你知道外部不存在任何的干扰代码,你可以扩展内置原型与检查方法。
//例子
var triangle = {a:1, b:2, c:3};
function ColoredTriangle() {
this.color = "red";
}
ColoredTriangle.prototype = triangle;
var obj = new ColoredTriangle();
for (var prop in obj) {
//判断是否为自身属性
if( obj.hasOwnProperty( prop ) ) {
console.log("o." + prop + " = " + obj[prop]);
}
}
// Output:
// "o.color = red"
2.for...of语句
for...of语句在可迭代对象(包括 Array, Map, Set, String, TypedArray,arguments 对象等等)上创建一个迭代循环,对每个不同属性的属性值,调用一个自定义的有执行语句的迭代挂钩。
//迭代 Array:
let iterable = [10, 20, 30];
for (let value of iterable) {
value += 1;
console.log(value);
}
// 11
// 21
// 31
//迭代 String:
let iterable = "boo";
for (let value of iterable) {
console.log(value);
}
// "b"
// "o"
// "o"
//迭代Map:
let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]);
for (let entry of iterable) {
console.log(entry);
}
// ["a", 1]
// ["b", 2]
// ["c", 3]
for (let [key, value] of iterable) {
console.log(value);
}
// 1
// 2
// 3
3.for...in和for...of的区别
for...in循环会遍历一个object所有的可枚举属性。
for...of语法是为各种collection对象专门定制的,并不适用于所有的object.它会以这种方式迭代出任何拥有[Symbol.iterator] 属性的collection对象的每个元素。
Object.prototype.objCustom = function () {};
Array.prototype.arrCustom = function () {};
let iterable = [3, 5, 7];
iterable.foo = "hello";
for (let i in iterable) {
console.log(i); // 0, 1, 2, "foo", "arrCustom", "objCustom"
}
for (let i of iterable) {
console.log(i); // 3, 5, 7
}
4.forEach
//参数:数组内容,数组索引,数组本身
[].forEach(function(value, index, array) {
// ...
},this);//this可选
5.map
原数组被“映射”成对应的新数组
[].map(function(value, index, array) {
// ...
});
6.forEach和map的区别
两个方法都是ES5中Array引进的新方法。
- forEach没有返回值,map返回一个新数组
- forEach不能链式调用,map可以
没有办法终止或者跳出forEach()循环,除非抛出异常,所以想执行一个数组是否满足什么条件,返回布尔值,可以用一般的for循环实现,或者用Array.every()或者Array.some();
总结
一般来说,遍历对象用for...in(最好先判断是否为自身属性),遍历数组用forEach(如果没有特殊操作的话)。