最近在项目中发现了一些遍历数组,对象时遇到的坑,一起来看看..
一、遍历数组
(1) forEach 不能跳出循环 (return, break, continue失效)
var arr = [1,2,3];
arr.forEach(i => {
console.log(i);
if (i === 2) return;
});
// 输出结果:
// 1
// 2
// 3
当时我就懵了,居然全部都输出了。然后继续测试,发现return, break, continue 都失效; 原以为forEach可以减少一些代码,发现不能跳出循环后,果断不用了,应用场景限制了太多。
2018-01-04 更新
(1) forEach 里面可以使用return, 会立即跳出当前循环, 继续执行下一个循环。 在函数中也是如此, 不会作为函数结果直接返回。
(2)forEach 中不支持 break, continue 关键字。其实, continue可以用return实现;break 跳出整个循环建议用 原生的for循环, 或者es6 的 for … of 实现。
(2) 同理 map循环,不能中断遍历
var arr = [1,2,3];
var newArr = arr.map(i => {
console.log(i);
if (i === 2) return i;
});
console.log(newArr);
// 输出结果
// 1
// 2
// 3
// [undefined, 2, undefined]
跟预期一样, map循环也不能终止遍历, 好在return语句生效了, 在newArr里有返回值。 另外,break,continue依然失效。
(3) for of循环, es6 遍历神器
var arr = [1, 2, 3];
for (let i of arr) {
console.log(i);
if (i === 2) break;
}
// 输出结果
// 1
// 2
for of 可以跳出循环了, 而且语法相对原始的for循环来说简洁一些, 支持return(函数里用), break, continue; 注意是es6的,nodejs可以用,前端就要转下了。
二、遍历对象
(1) for in 可以跳出循环
var obj = {name: 'bob', age: 25, gender: 'male'};
for (let key in obj) {
console.log(key);
if (key === 'age') break;
}
// 输出结果:
// name
// age
很不错, for in 可以跳出循环, 但是坑在后面..
(2) for in 会遍历原型对象上的属性
var obj = {name: 'bob', age: 25, gender: 'male'};
obj.__proto__.test = 'test prototype';
for (let key in obj) {
console.log(key);
}
// 输出结果:
// name
// age
// gender
// test
我们发现for … in 会遍历对象原型链上的属性,有时候是意想不到的错误。 解决方法: 判断是否自身属性即可, obj.hasOwnProperty()。
var obj = {name: 'bob', age: 25, gender: 'male'};
obj.__proto__.test = 'test prototype';
for (let key in obj) {
if (obj.hasOwnProperty(key))
console.log(key);
}
// 输出结果:
// name
// age
// gender
三、总结
(1) 遍历数组,在前端尽量用原始的for循环, 如果有支持es6,就用for … of; node端用for of,简洁。
(2) forEach, map 根据实际场景使用,注意上面的坑。
(3) 遍历对象用 for … in 注意增加判断 hasOwnProperty。