背景
面试了一个小伙伴,自称资深前端,精通Js、精通Vue,工作 6 年。
我们也不玩虚的,让他觉得 面试造火箭,工作拧螺丝
,那就来点实在的。
问1:你知道Js可以实现数组遍历的有哪些方法?
答1:for、for/in、for/of、forEach、map 等等反正都可以用来遍历”
问2:那这些方法中哪些可以中断?
答2:好像 for 不可以,好像 for/in 可以,....
语无伦次,陷入沉思。
来来来,各位看官,如果你也不知道,那么看完本文可以 收藏+点赞
鼓励一波。
数组遍历的方法
方法一览
- for
- for/in
- for/of
- Array.forEach
- Array.map
- Array.reduce
- Array.filter
- Array.some
- Array.every
每个方法就不一一唠叨,这里敲重点介绍。
for/in 和 for/of 区别
重点说明:
- for/in 以任意顺序遍历一个对象的除 Symbol 以外的 可枚举 属性。所以,for/in 一般用来遍历对象。
- for/of 在 可迭代对象(包括
Array
,Map
,Set
,String
,TypedArray
,arguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。所以,for/of 一般用来遍历数组。
注意:
- for/in 是无序的,遍历使用时需要注意,参考:JS解惑-Object中的key是有序的么?
- 啥是
可枚举
?仔细看看: 可枚举
重点示例:
// 二者都来遍历对象
let obj = {
id: 1,
name: 'lilei'
};
// for/in
for (var o in obj) {
console.log(o);
};
// Output
// id
// name
// for/of
for (var o of obj) {
console.log(o);
};
// Error 对象不是一个迭代器,不能使用 for/of
// VM319:1 Uncaught TypeError: obj is not iterable
可以看出,for/of 是无法遍历一个对象的。
// 二者都来遍历数组
let ary = ['a', 'b', 'c'];
// 注意:数组也是一个特殊的对象,我给数组增加一个属性
ary.name = 'james';
// for/in
for (var o in ary) {
console.log(o);
};
// Output 打印数组索引和name属性值(注意)!
// 0
// 1
// 2
// james
// for/of
for (var o of ary) {
console.log(o);
};
// Output 只打印数组每个元素
// a
// b
// c
所以,for/of
在 ES6 的出现一定程度也是弥补 for/in
在遍历数组上的缺陷。
Array.map
重点说明:
- 创建一个新的数组(不要忘记把
map
结果赋值给遍历,否则就浪费一次遍历) - 原始数组不受影响(除非你把
map
当forEach
使用,直接在循环中修改原数组的值) - 新数组的每个结果是回调函数中返回的值(如果你回调函数忘记
reture
那新数组每个元素可都是undefined
)
典型错误案例:
把 map
用来遍历数组,map
中直接修改原数组的值
错误示例:
let demoAry = [{
value: 1
}, {
value: 2
}];
demoAry.map(item => {
item.value = item.value * 2
});
console.log(demoAry);
正确示例:
let demoAry = [{
value: 1
}, {
value: 2
}];
// 方法1:forEach 遍历数组
demoAry.forEach(item => {
item.value = item.value * 2
});
console.log(demoAry);
//方法2:map 生成新的数组替换原数组
demoAry = demoAry.map(item => {
item.value = item.value * 2;
return item;
});
console.log(demoAry);
Array.reduce
重点说明:
- 产生一个新的结果,结果取决于回调函数
return
的值 - 原始数组不受影响(除非你把
reduce
当forEach
使用,直接在循环中修改原数组的值) - 接收2个参数,callback 和 initialValue
-
callback 有4个参数:
累加值
、当前值
、当前索引
、原始值
,一般用前2个参数 - initialValue 可选,如果省略默认取第1个元素,但如果数组也是空的,那将会报错
重点示例:
// 有初始值
[1, 2, 3, 4, 5].reduce((acc, cur) => {
console.log(acc, cur);
return acc + cur;
}, 100);
// Output 遍历5次,最终返回 int 求和结果 115
// 100 1
// 101 2
// 103 3
// 106 4
// 110 5
// 115
无初始值,遍历会少一次,因为数组第一个结果充当了迭代器的第一个值。
// 无初始值
[1, 2, 3, 4, 5].reduce((acc, cur) => {
console.log(acc, cur);
return acc + cur;
});
// Output 遍历4次,最终返回 int 求和结果 15
// 1 2
// 3 3
// 6 4
// 10 5
// 15
Array.some 和 Array.every
二者都是用来判断数组中是否有满足条件的元素,返回结果 true
or false
重点说明:
- 二者使用时,你一定需要明确什么时候该
return true or false
,判断出结果即可
注意用法 | |
---|---|
some | 找到一个 满足条件 时,需要 return true ,跳出循环,没必要再继续找了,结果就是 true
|
every | 找到一个 不满足条件 时,需要 return false ,跳出循环,没必要再继续找了,结果就是 false
|
重点示例:
// some
[1, 2, 3, 4, 5].some(item => {
console.log(item);
if (item === 3) {
return true;
};
// 默认是 false,可以省略。表示找不到,会继续遍历查找到数组最后一个
return false;
});
// Output 遍历3次,找到结果返回 true
// 1
// 2
// 3
// true
// every
[1, 2, 3, 4, 5].every(item => {
console.log(item);
if (item === 3) {
return false;
};
// 默认是 false,必须写。如果不显性的说明本次 true,表明第1个元素就不合适,直接就退出了。
return true;
});
// Output 遍历3次,找到不合适的结果返回 false
// 1
// 2
// 3
// false
哪些方法可以中断
我们先了解下中断一个数组遍历的办法:
- break
- throw
- return
- continue(立即结束本次循环continue后面代码不执行,进入下一轮循环,算是中止当前循环,勉强也算)
方法一览
这些方法中,我们要 中断
一个数组常用的方法就是 Array.some
和 Array.every
,因为一定是符合/不符合某些条件下,你才会中断一个数组遍历,不是么?用这2个语法糖可能更恰当一些。
for
// for break
let ary = [1, 2, 3, 4, 5];
for (let i=0; i< ary.length; i++) {
console.log(i);
if(i === 3) {break;};
};
// Output
// 0
// 1
// 2
// 3
// --------------------------
// for continue
for (let i=0; i< ary.length; i++) {
console.log('before=', i);
if(i === 3) {continue;};
console.log('after=', i);
};
// Output 注意没有 after=3
// before= 0
// after= 0
// before= 1
// after= 1
// before= 2
// after= 2
// before= 3
// before= 4
// after= 4
for/of
// for/of break
let ary = [1, 2, 3, 4, 5];
for (let o of ary) {
console.log(o);
if(o === 3) {break;};
};
// Output
// 1
// 2
// 3
// --------------------------
// for/of continue
for (let o of ary) {
console.log('before=', o);
if(o === 3) {continue;};
console.log('after=', o);
};
// Output 注意没有 after=3
// before= 1
// after= 1
// before= 2
// after= 2
// before= 3
// before= 4
// after= 4
// before= 5
// after= 5
Array.some 和 Array.every
用法参考上文,不再赘述
这2个方法与 for
和 for/of
的区别需要注意,他们中断的语法是 return
,不能使用 break
或者 continue
。
(全文完)
网友评论