Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

你连 Js 数组遍历都无法中断还敢自称资深前端? #70

Open
sunmaobin opened this issue Aug 18, 2020 · 0 comments
Open

你连 Js 数组遍历都无法中断还敢自称资深前端? #70

sunmaobin opened this issue Aug 18, 2020 · 0 comments
Assignees
Projects
Milestone

Comments

@sunmaobin
Copy link
Owner

你连 Js 数组遍历都无法中断还敢自称资深前端?

背景

面试了一个小伙伴,自称资深前端,精通Js、精通Vue,工作 6 年。

我们也不玩虚的,让他觉得 面试造火箭,工作拧螺丝,那就来点实在的。

问1:你知道Js可以实现数组遍历的有哪些方法?

答1:for、for/in、for/of、forEach、map 等等反正都可以用来遍历”

问2:那这些方法中哪些可以中断?

答2:好像 for 不可以,好像 for/in 可以,.... 语无伦次,陷入沉思。

来来来,各位看官,如果你也不知道,那么看完本文可以 收藏+点赞 鼓励一波。

数组遍历的方法

方法一览

  1. for
  2. for/in
  3. for/of
  4. Array.forEach
  5. Array.map
  6. Array.reduce
  7. Array.filter
  8. Array.some
  9. Array.every

每个方法就不一一唠叨,这里敲重点介绍。

for/in 和 for/of 区别

重点说明:

  • for/in 以任意顺序遍历一个对象的除 Symbol 以外的 可枚举 属性。所以,for/in 一般用来遍历对象。
  • for/of 在 可迭代对象(包括 ArrayMapSetStringTypedArrayarguments 对象等等)上创建一个迭代循环,调用自定义迭代钩子,并为每个不同属性的值执行语句。所以,for/of 一般用来遍历数组。

注意:

重点示例:

// 二者都来遍历对象
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 结果赋值给遍历,否则就浪费一次遍历)
  • 原始数组不受影响(除非你把 mapforEach 使用,直接在循环中修改原数组的值)
  • 新数组的每个结果是回调函数中返回的值(如果你回调函数忘记 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 的值
  • 原始数组不受影响(除非你把 reduceforEach 使用,直接在循环中修改原数组的值)
  • 接收2个参数,callbackinitialValue
  • 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.someArray.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个方法与 forfor/of 的区别需要注意,他们中断的语法是 return,不能使用 break 或者 continue

(全文完)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
前端
Awaiting triage
Development

No branches or pull requests

1 participant