javascript 一些循环方法

    xiaoxiao2024-11-12  68

    遍历数组有很多方法, 最简单的便是for循环, 另外还有forEach、map、filter、some、every、reduce等 ; 每种方法面向的场景是不一样的, 先讲一下使用, 性能嘛, 最后再看

    for

    for循环是最基础的一种循环方式

    // 一般把长度先缓存, 避免重复获取, 无需多言 const arr = [1,2,3,4,5] const len = arr.length; for(i = 0; i < len; i++) { // do something }

    for循环可以通过break、return 等语句提前终止 for并没有块级作用域 当遇到return语句时 , 包含此for循环的方法会终止

    const gg = () => { const arr = [1,2,3,4,5] const len = arr.length for(i = 0; i < len; i++) { console.log(arr[i]) if(i === 3) { return } } console.log('last') } // return 后 'last' 不打印 gg() // 1 2 3 4

    字符串同样有length属性, 所以可以遍历字符串

    forEach

    一般用于对数组每一项进行修改, 没有返回值

    arr.forEach(_ => { // do something })

    由于break, continue只能在循环中使用, 而forEach回调function是函数 很明显不可以通过break, continue等中断循环 但是可以通过return结束本次循环

    [1,2,3,4,5].forEach(_ => { if(_ === 3) { return } console.log(_) }) // 1 2 4 5 // 可以看到3 没有被打印, 循环仍会继续, 所以 4 5 被打印了

    如果要我非要终止循环呢, 也不是不行, 不过我暂时只能想到抛异常的方法

    try{ [1,2,3,4,5].forEach(_ => { if(_ === 3) { throw new Error('end') } console.log(_) }) }catch(e){ console.log(e) } // 1 2 // throw new Error('end') 是一种方法

    Set, Map原型中包含forEach方法, 所以可以用于遍历Set, Map, 并不需要 Array.forEach.call / apply 的方式去做

    Set.prototype.forEach // ƒ forEach() { [native code] } Map.prototype.forEach // ƒ forEach() { [native code] }

    那么 Set 和 Map 调用 forEach 打印的 index, value都是什么呢

    new Set(['one','two','three', NaN, NaN]).forEach((value, index, set) => { console.log(index) console.log(value) }) //one //one //two //two //three //three //NaN //NaN // 可以看到, Set.forEach打印的index, value都是元素本身 // 题外话, 另一个有趣现象是, 我在new Set()传入了两个NaN, 由于Set不允许重复元素, 所以最后只会存在一个NaN值 // 但是, 不是说 NaN !== NaN 吗? 我认为, Set内部做了处理, 具体如何处理爹也不大明白 //-------------------------------------------------- //再看Map new Map([["key1", "value1"], ["key2", "value2"]]).forEach((value, index, map) => { console.log(index) console.log(value) }) //key1 //value1 //key2 //value2 //可以看到, index为元素的键, value为元素的值

    map

    一般是对每个元素进行一些处理, 并返回新的数组

    arr.map((el, index) => { // do something with el return el })

    Set, Map没有该方法

    常见用法

    const arr = [{id: '46548', name: 'faker'}, {id: '46549', name: 'faker2'}] const idList = arr.map(el => el.id) console.log(idList) // ['46548', '46549']

    filter / find

    filter 用来查找符合条件的元素集合 find 找到第一个符合条件的元素并返回, 找到后不再往下遍历

    every / some

    这两个方法更多地用在测试数组的个性 every 测试数组内的所有元素是否都能通过某个指定函数的测试, 最终返回布尔值, 只要有一个元素不通过则终止循环并返回 false

    const arr = [10, 30, 8, 2, 6] let bool = arr.every(el => { return el % 2 === 0 }) bool // true // 每个元素除以2余数都为0吗, 很明显, 是的

    some测试是否至少有一个元素通过由提供的函数实现的测试, 最终返回布尔值, 只要有一个元素通过则终止循环并返回 true

    const arr = [1, 2, 7, 11, 6] let bool = arr.some(el => { return el % 2 === 0 }) bool // true // 至少有一个元素除以2余数为0吗, 很明显, 是的

    for in

    for in 循环可以遍历字符串、对象、数组,不能遍历 Set/Map, 并且只能拿到可枚举的(enumerable)属性 需要注意的是, in 可以拿到原型上的属性

    let obj = { [Symbol('one')]: 22, one: 11, two: 22 } obj.__proto__.name = "haha" for(let v in obj){ console.log(v) } // one, two, name // 这里用symbol作为键时, 该属性是不可枚举的, 所以for in取不到 // 把one属性改为不可枚举 Object.defineProperty(obj, 'one', { enumerable: false }) // 这个时候就取不到one了 for(let v in obj){ console.log(v) } // two, name

    还有, 如果给数组加上属性, 也会被迭代出来

    const arr = [1,2,3] arr.name = 'haha' // name属性也会被遍历出来 for(let v in arr){ console.log(v) } // 0,1,2,name

    因为迭代的顺序是依赖于执行环境的,所以数组遍历不一定按次序访问元素。因此当迭代访问顺序很重要的数组时,最好用整数索引去进行for循环

    for of

    遍历Array可以采用下标循环,遍历Map和Set就无法使用下标。 为了统一集合类型,ES6标准引入了新的iterable类型,Array、Map和Set都属于iterable类型, 也就是可迭代对象 for of 循环不仅支持数组、大多数伪数组对象,也支持字符串遍历,此外还支持 Map 和 Set 对象遍历

    let iterable = new Map([["a", 1], ["b", 2], ["c", 3]]); for (let [key, value] of iterable) { console.log(key); console.log(value); } // a // 1 // b // 2 ... ...

    区别 for…in 语句以原始插入顺序迭代对象的可枚举属性, 拿到的是键 for…of 语句遍历可迭代对象定义要迭代的数据, 拿到的是值

    最新回复(0)