一、for...in
1、枚举对象
var obj = {
a: 1,
b: [],
c: function () {}
};
for (var key in obj) {
console.log(key);
}
// 结果是:
// a
// b
// c
2、枚举数组
for..in不仅可以枚举数组自身,
var arr = [3, 5, 7];
for (var i in arr) {
console.log(i, arr[i]);
}
// 结果是:
// 0 3
// 1 5
// 2 7
还能枚举数组的原型对象以及数组对象本身属性值。
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
var arr = [3, 5, 7];
arr.foo = 'hello';
for (var i in arr) {
console.log(i);
}
// 结果是:
// 0
// 1
// 2
// foo
// arrCustom
// objCustom
在实际工作开发中,原型对象很可能是不需要的,不需要全部枚举出来。
此时,可以使用JS的内置对象方法hasOwnProperty来避免这个问题。
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
var arr = [3, 5, 7];
arr.foo = 'hello';
for (var i in arr) {
if (arr.hasOwnProperty(i)) {
console.log(i);
}
}
// 结果是:
// 0
// 1
// 2
// foo
但是用这个办法,依然无法摆脱数组本身的属性。
此时,可以使用数组方法forEach来解决这个问题。
Object.prototype.objCustom = function() {};
Array.prototype.arrCustom = function() {};
var arr = [3, 5, 7];
arr.foo = 'hello';
arr.forEach(function (value, i) {
console.log(i);
});
// 结果是:
// 0
// 1
// 2
3、枚举字符串
for in的枚举字符串是在IE9+之后才支持的。
let str = 'boo';
for (let value in str) {
console.log(value, str[value]);
}
// 结果是:
// "b"
// "o"
// "o"
// d ƒ (e){return this||e||""}
// defaultMessage ƒ (e){return this||e||""}
二、for...of
1、枚举对象
var obj = {
a: 1,
b: [],
c: function () {}
};
for (var key of obj) {
console.log(key);
}
// 出错:
// Uncaught TypeError: obj is not iterable
2、迭代数组
for..of对数组的枚举是直接输出了数组的值,无法获取数组的索引。
key
var arr = [3, 5, 7];
for (var i of arr) {
console.log(i);
}
// 结果是:
// 3
// 5
// 7
3、迭代字符串
let str = 'boo';
for (let value of str) {
console.log(value);
}
// 结果是:
// "b"
// "o"
// "o"
4、迭代arguments类数组对象
(function() {
for (let argument of arguments) {
console.log(argument);
}
})(1, 2, 3);
// 结果是:
// 1
// 2
// 3
5、迭代NodeList这类DOM集合
for of迭代NodeList这类DOM集合时,无需[].slice.call(),也不需要Array.from()进行数组转化。
let elements = document.querySelectorAll('body');
for (let element of elements) {
console.log(element.tagName);
}
// 结果是:
// "BODY"
6、迭代类型数组
let typeArr = new Uint8Array([0x00, 0xff]);
for (let value of typeArr) {
console.log(value);
}
// 结果是:
// 0
// 255
7、迭代Map和Set
let mapData = new Map([['a', 1], ['b', 2], ['c', 3]]);
for (let [key, value] of mapData) {
console.log(value);
}
// 结果是:
// 1
// 2
// 3
let setData = new Set([1, 1, 2, 2, 3, 3]);
for (let value of setData) {
console.log(value);
}
// 结果是:
// 1
// 2
// 3
三、总结
1、for in与for of相比
对于纯对象的遍历,使用for..in更合适;
对于数组遍历,如果不需要知道索引,for..of迭代更合适,因为还可以中断;
对于数组遍历,如果需要知道索引,则forEach()更合适;
对于其他字符串、类数组、类型数组的迭代,虽然for..in也有这方面能力,使用for..of更方便;
对于兼容性,果断使用for..in,因为for..of是S6新特性,IE浏览器不支持。(微笑)
2、forEach与for of相比
两者都可以遍历数组,但forEach遍历数组时无法break或return false中断遍历,而这一点for of可以做到。
var arr = [3, 5, 7];
arr.forEach(function (value) {
console.log(value);
if (value == 5) {
return false;
}
});
// 结果是:
// 3
// 5
// 7
var arr = [3, 5, 7];
for (let value of arr) {
console.log(value);
if (value == 5) {
break;
}
}
// 结果是:
// 3
// 5
枚举与迭代的区别
枚举:指调用一个枚举函数、一次性列举出集合中的元素,通常需要指定一个触发器函数作为参数。
迭代:迭代函数通常用于for...in语句中,创建一个迭代器,用以遍历集合成员。1、枚举一般指使用回调触发器机制来遍历对象;而迭代一般是使用用for...in语句来循环迭代对象。
2、枚举是一次性列举出集合中的元素;迭代函数不是一次性列举出所有元素,他是在一个循环中每次迭代出集合中的一个成员。
3、枚举可以通过返回值来被动退出遍历过程;而迭代随时可以用break语句来主动中断遍历过程,在控制上更自由一些。
4、这就好象演出,枚举是一次性全站台上;而迭代是一个一个的轮流上台,随时可以叫停。
5、迭代是广度遍历,通常在同一深度遍历集合对象;而枚举是枚举可以通过递归深度遍历集合。
网友评论