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

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

作者: 村口蹲一郎v | 来源:发表于2020-08-18 19:12 被阅读0次

    背景

    面试了一个小伙伴,自称资深前端,精通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

    (全文完)

    相关文章

      网友评论

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

          本文链接:https://www.haomeiwen.com/subject/nwwkjktx.html