zoukankan      html  css  js  c++  java
  • JavaScript数组遍历的十五种方法

    数组方法:map

    • 核心

      • 创建一个新数组,其结果是该数组中的每个元素都调用一个提供的函数后返回的结果。
      • 不改变原数组
      • 返回值是一个新的数组
    • 缺陷

      • 可以使用return,但是不能使用break和continue
    • 回调函数参数

      • 第一个参数:item 数组中的子元素
      • 第二个元素:index 数组元素的索引值
      • 第三个元素:arr 原数组
        let fruits= ['苹果', '梨子', '桃子', '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
        // 数组方法:map
        let mapFru= fruits.map(function(item, index, arr){
            item= `${item}啊!`;
            console.log(arr);
            return index+ ' - 爱吃'+ item;
        });
        console.log(mapFru);
        console.log('-------------------------');
        let mapVeg= vegetables.map(function(item, index, arr){
            // 返回 遍历子对象
            console.log(item);
            // 返回 遍历索引值
            console.log(index);
            // 返回 所有子对象
            console.log(arr);
        });
    

    数组方法 forEach

    • 核心

      • 对数组的每个元素执行一次提供的函数。
      • 不改变原数组
      • 返回值总是undefined
      • map是forEach操作的具体化
    • 缺陷

      • 可以使用return,但是不能使用break和continue
    • 回调函数参数

      • 第一个参数:item 数组中的子元素
      • 第二个元素:index 数组元素的索引值
      • 第三个元素:arr 原数组
        let fruits= ['苹果', '梨子', '桃子', '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
    
        // 数组方法:forEach
        let forEachFru= fruits.forEach(function(item, index, arr){
            item= `${item}啊!`;
            // console.log(item);
            // console.log(index);
            // console.log(arr);
            return index+ ' - 爱吃'+ item;
        });
        console.log(forEachFru);
        console.log('-------------------------');
        let forEachVeg= vegetables.forEach(function(item, index, arr){
            // 返回 遍历子对象
            console.log(item);
            // 返回 遍历索引值
            console.log(index);
            // 返回 所有子对象
            console.log(arr);
        });
    
    • 手动封装一个forEach
       // 封装一个数组的 myForEach 方法 传参为一个函数
       function myForEach(fn){
            // 循环数组的每一项   谁调用的this就指向谁
            for(let i = 0; i < this.length; i++){
                // 循环传进来的函数的三个参数
                fn(this[i],i,this)
            }
        }
        // 定义一个数组
        let arr = ['4','5','6']
        // 将定义的这个数组方法放到Array的prototype下面
        Array.prototype.myForEach = myForEach;
        console.log(Array.prototype)
        // 数组arr调用myForEach方法并传参
        arr.myForEach(function(item,index,arr){
            // 打印传进来的参数
            console.log(item,index,arr)
        })
    

    数组方法 filter

    • 核心

      • 对数组的每一项都进行过滤,返回符合条件的item组成的数组
      • 不改变原数组
      • 返回值是经过逻辑判断后,调用数组的一个子集
      • 没有任何的逻辑判断,可替代map或forEach使用,返回值为原数组
    • 优点:

      • 若是arr.filter(function(){return true}),则会跳过数组中缺少的元素,它的返回数组总是稠密的
      • 返回值为判断语句,则可方便筛选提取数组内的对象元素
    • 缺陷

      • 可以使用return,但是不能使用break和continue
    • 回调函数参数

      • 第一个参数:item 数组中的子元素
      • 第二个元素:index 数组元素的索引值
      • 第三个元素:arr 原数组
        let fruits= ['苹果', '梨子', '桃子',, '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
    
        // 数组方法:filter
        let filterFru= fruits.filter(function(item, index, arr){
            item= `${item}啊!`;
            console.log(item);
            // console.log(index);
            // console.log(arr);
            return true;
        });
        console.log(filterFru);
        console.log('-------------------------');
        let filterVeg= vegetables.filter(function(item, index, arr){
            // 返回 遍历子对象
            // console.log(item);
            // // 返回 遍历索引值
            console.log(index);
            // // 返回 所有子对象
            // console.log(arr);
            return item.id== 2;
        });
        console.log(filterVeg);
    
    • 压缩空缺并删除undefinednull元素
    arr= arr.filter(function(index){
        return index!== undefined && index!= null;
    });
    

    数组方法 find

    • 核心

      • 遍历数组,找到第一个符合条件的项,并返回该项。否则返回undefined
      • 不改变原数组
      • 返回值为true,则返回第一个元素
      • 当找到目标值后,停止遍历,并返回目标元素
    • 缺陷

      • 可以使用return,但是不能使用break和continue
    • 回调函数参数

      • 第一个参数:item 数组中的子元素
      • 第二个元素:index 数组元素的索引值
      • 第三个元素:arr 原数组
        let fruits= ['苹果', '梨子', '桃子',, '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
        // 数组方法:find
        let findFru= fruits.find(function(item, index, arr){
            item= `${item}啊!`;
            // console.log(item);
            // console.log(index);
            // console.log(arr);
            return index> 1;
        });
        console.log(findFru);
        console.log('-------------------------');
        let findVeg= vegetables.find(function(item, index, arr){
            // 返回 遍历子对象
            // console.log(item);
            // // 返回 遍历索引值
            console.log(index);
            // // 返回 所有子对象
            // console.log(arr);
            return item.id> 1;
        });
        console.log(findVeg);
    

    数组方法 findIndex

    • 核心

      • 遍历数组,找到第一个符合条件的项,并返回该项。否则返回-1
      • 不改变原数组
    • 缺陷

      • 可以使用return,但是不能使用break和continue
    • 回调函数参数

      • 第一个参数:item 数组中的子元素
      • 第二个元素:index 数组元素的索引值
      • 第三个元素:arr 原数组
        let fruits= ['苹果', '梨子', '桃子',, '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
    
        // 数组方法:findIndex
        let findIndexFru= fruits.findIndex(function(item, index, arr){
            // item= `${item}啊!`;
            // console.log(item);
            // console.log(index);
            // console.log(arr);
            return index> 5;
        });
        console.log(findIndexFru);
        console.log('-------------------------');
        let findIndexVeg= vegetables.findIndex(function(item, index, arr){
            // 返回 遍历子对象
            console.log(item.name);
            // // 返回 遍历索引值
            // console.log(index);
            // // 返回 所有子对象
            // console.log(arr);
            return item.id> 2;
        });
        console.log(findIndexVeg);
    

    数组方法 indexOf

    • 核心

      • 从前往后遍历数组,找到第一个符合条件的项,并返回该项。否则返回-1
      • 不改变原数组
      • 字符串也有此方法,功能类似
    • 回调函数参数

      • 第一个参数:item 需要搜索的值
      • 第二个元素:index 数组中的的索引值,可以为负数,代表相对数组末尾的偏移量
        let fruits= ['苹果', '梨子', '桃子', , '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
    
        // 数组方法:indexOf
        let indexOfFru= fruits.indexOf('桃子');
        console.log(indexOfFru);
    

    数组方法 lastIndexOf

    • 核心

      • 从后往前遍历数组,找到第一个符合条件的项,并返回该项。否则返回-1
      • 不改变原数组
      • 字符串也有此方法,功能类似
    • 回调函数参数

      • 第一个参数:item 需要搜索的值
      • 第二个元素:index 数组中的的索引值,可以为负数,代表相对数组末尾的偏移量
        let fruits= ['苹果', '梨子', '桃子', , '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
    
        // 数组方法:lastIndexOf
        let lastIndexOfFru= fruits.lastIndexOf('桃子');
        console.log(lastIndexOfFru);
    

    数组方法 every

    • 核心

      • 对数组中的每一项运行给定函数,如果该函数对每一项返回true,则返回true。
      • 类似数学中的'针对所有',看数组的每个元素是否符合要求,都符合则返回true,否则返回false
    • 缺陷

      • 可以使用return,但是不能使用break和continue
    • 回调函数参数

      • 第一个参数:item 数组中的子元素
      • 第二个元素:index 数组元素的索引值
      • 第三个元素:arr 原数组
        let fruits= ['苹果', '梨子', '桃子',, '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
    
        // 数组方法:every
        let everyFru= fruits.every(function(item, index, arr){
            // item= `${item}啊!`;
            // console.log(item);
            // console.log(index);
            // console.log(arr);
            return index< 6;
        });
        console.log(everyFru);
        console.log('-------------------------');
        let everyVeg= vegetables.every(function(item, index, arr){
            // 返回 遍历子对象
            // console.log(item);
            // // 返回 遍历索引值
            console.log(index);
            // // 返回 所有子对象
            // console.log(arr);
            return item.id>= 0;
        });
        console.log(everyVeg);
    

    数组方法 some

    • 核心

      • 是对数组中每一项运行指定函数,如果该函数对任一项返回true,则返回true。
      • 类似数学中的'存在',看数组的每个元素是否符合要求,任一项返回true,否则返回true
    • 缺陷

      • 可以使用return,但是不能使用break和continue
    • 回调函数参数

      • 第一个参数:item 数组中的子元素
      • 第二个元素:index 数组元素的索引值
      • 第三个元素:arr 原数组
    • 关于return

      • return true; 遍历终止
        changeNum: function(val){
            // console.log(val);
            // 根据子组件传过来的数据,更新list中对应的数据
            this.list.some(function(item){
            if(item.id == val.id){
                item.num= val.num;
                // 终止遍历
                return true;
            }
            })
        }
    
        let fruits= ['苹果', '梨子', '桃子',, '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
        // 数组方法:some
        let someFru= fruits.some(function(item, index, arr){
            // item= `${item}啊!`;
            // console.log(item);
            // console.log(index);
            // console.log(arr);
            return index< 6;
        });
        console.log(someFru);
        console.log('-------------------------');
        let someVeg= vegetables.some(function(item, index, arr){
            // 返回 遍历子对象
            // console.log(item);
            // // 返回 遍历索引值
            console.log(index);
            // // 返回 所有子对象
            // console.log(arr);
            return item.id>= 0;
        });
        console.log(someVeg);
    

    数组方法 reduce

    • 核心

      • 接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。
      • 第二个参数作为第一次调用的a的值
    • 缺陷

      • 可以使用return,但是不能使用break和continue
        let arrNum= [2, 4, 6, 8, 10];
        // 累加
        let sum= arrNum.reduce(function(x, y){
            return x+ y;
        }); 
        console.log(sum);
    
        // 累乘
        let multiple= arrNum.reduce(function(x, y){
            return x* y;
        }); 
        console.log(multiple);
    
        // 求最大值
        let bigger= arrNum.reduce(function(x, y){
            return x> y? x: y;
        }); 
        console.log(bigger);
    

    数组方法 reduceRight

    • 核心

      • 接收一个函数作为累加器(accumulator),数组中的每个值(从右到左)开始缩减,最终为一个值。
      • 第二个参数作为第一次调用的a的值
    • 缺陷

      • 可以使用return,但是不能使用break和continue
        let arrNum= [2, 4, 6, 8, 10];
        // 累加
        let sum= arrNum.reduceRight(function(x, y){
            return x+ y;
        }); 
        console.log(sum);
    
        // 累乘
        let multiple= arrNum.reduceRight(function(x, y){
            return x* y;
        }); 
        console.log(multiple);
    
        // 求最大值
        let bigger= arrNum.reduceRight(function(x, y){
            return x> y? x: y;
        }); 
        console.log(bigger);
    

    逻辑方法 for循环

    • 核心

      • 使用临时变量,并且遍历的是i.
    • 缺陷

      • 可以正常使用使用break和continue, 但是不能正常使用return
        let fruits= ['苹果', '梨子', '桃子', , '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
    
        // 逻辑方法:for循环
        for(let i= 0; i<fruits.length; i++){
            console.log(fruits[i]);
        }
    
        console.log('-------------------------');
        
        for(let i= 0; i<vegetables.length; i++){
            console.log(vegetables[i].name);
        }
    

    逻辑方法 for...in...循环

    • 核心

      • 使用临时变量,并且遍历的是key.
    • 缺陷

      • 可以正常使用使用break和continue, 但是不能正常使用return
        let fruits= ['苹果', '梨子', '桃子', , '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
    
        // 逻辑方法:for...in...循环
        for(let key in fruits){
            console.log(fruits[key]);
        }
    
        console.log('-------------------------');
        
        for(let key in vegetables){
            console.log(key);
            console.log(vegetables[key].name);
        }
    

    逻辑方法 for...of...循环

    • 核心

      • 使用临时变量,并且遍历的是value.
    • 缺陷

      • 可以正常使用使用break和continue, 但是不能正常使用return
        let fruits= ['苹果', '梨子', '桃子', , '西瓜', '哈密瓜'];
        let vegetables= [{
            id: 1,
            name: '花椰菜'
        },{
            id: 2,
            name: '青椒'
        },{
            id: 3,
            name: '土豆'
        },{
            id: 4,
            name: '西红柿'
        }];
    
        // 逻辑方法:for...of...循环
        for(let value of fruits){
            console.log(value);
        }
    
        console.log('-------------------------');
        
        for(let value of vegetables){
            console.log(value);
            console.log(value.name);
        }
    

    遍历器机制

    • 背景

      • 截止到ES6,JavaScript 已经拥有了数组、对象、Map集合和Set集合这样四种数据结构
      • 为了统一和简化遍历这四种数据结构的操作,ES6引入了遍历器机制。
    • 关于setmap

        var set = new Set();  
        set.add("a").add("b").add("d").add("c");  
        console.log(set);
    
        var map = new Map();  
        map.set("a",1).set("b",2).set(999,3);  
        console.log(map);
    
        for (let value of set) {  
            console.log(value);  
        }  
        console.log("--------------------");  
        for(let [key, value] of map) {  
            console.log(key, value);  
        }  
    
    • 基本概念
      • ES6 规定,可遍历的对象都具有Symbol.iterator 属性,这个属性指向一个函数,就是当前对象默认的遍历器生成函数。
      • 这个遍历器生成函数大致的模样可以用ES5 语法模拟出来:这个函数返回一个next() 方法,每调用next() 方法,都会返回数据结构的当前成员的信息。
      • 具体来说,就是返回一个包含value和done两个属性的对象。
      • 其中,value属性是当前成员的值,done属性是一个布尔值,表示遍历是否结束。
    // ES5 语法模拟遍历器
    function createIterator(items) {
        let i = 0;
        return {
            next() {
                let done = i >= items.length;
                let value = !done ? items[i++] : undefined;
                return {
                    done: done,
                    value: value
                }
            }
        }
    }
    
    let iterator = createIterator([1, 2, 3]);
    console.log(iterator.next()); 
    //输出:{done: false, value: 1}
    console.log(iterator.next()); 
    //输出:{done: false, value: 2}
    console.log(iterator.next()); 
    //输出:{done: false, value: 3}
    console.log(iterator.next()); 
    //输出:{done: true, value:undefined }
    
    • 默认遍历器

      • 在ES6 中,已经默认为绝大多数內建的数据结构提供了遍历器,不需要像上面例子中那样自己去创建。
      • keys()方法:默认遍历器,其值为集合中的所有键名。
      • values()方法:默认遍历器,其值为集合中的所有值。
      • entries()方法:默认遍历器,其值为所有成员的键值对。
    • 注意:

      • 扩展运算符(…)会持续调用遍历器的next() 方法,并将value属性值插入到数组中,直到结果对象的done 属性值为true。
      • Set 集合的键名和键值是同一个值,所以keys() 方法和values() 方法的返回值完全一致。
    const arr = ["A", "B", "C"];
    console.log([...arr.keys()]); 
    //输出:[0, 1, 2]
    console.log([...arr.values()]); 
    //输出:["A", "B", "C"]
    console.log([...arr.entries()]); 
    //输出:[[0, "A"],[1, "B"],[2, "C"]]
    
    const set = new Set(arr);
    console.log([...set.keys()]); 
    //输出:["A", "B", "C"]
    console.log([...set.values()]); 
    //输出:["A", "B", "C"]
    console.log([...set.entries()]); 
    //输出:[["A", "A"],["B", "B"],["C", "C"]]
    
    const map = new Map().set("name", "Tom").set("age", 19);
    console.log([...map.keys()]); 
    //输出:["name", "age"]
    console.log([...map.values()]); 
    //输出:["Tom", 19]
    console.log([...map.entries()]); 
    //输出:[["name", "Tom"],["age", 19]]
    
    • 不同数据结构的默认遍历器
      • 每个数据结构都有一个默认的遍历器,例如数组的默认遍历器是values()
        ,在没有明确指定遍历器的情况下,这些数据结构都会使用默认的遍历器。
      • 我们可以通过检测对象的Symbol.iterator 属性来判断对象是否拥有遍历器。
    const arr = ["A", "B", "C"];
    console.log(typeof arr[Symbol.iterator] === "function"); 
    //输出:true
    console.log(arr[Symbol.iterator]); 
    //输出:function values() { ... }
    
    const set = new Set(arr);
    console.log(typeof set[Symbol.iterator] === "function"); 
    //输出:true
    console.log(set[Symbol.iterator]); 
    //输出:function values() { ... }
    
    const map = new Map().set("name", "Tom").set("age", 19);
    console.log(typeof map[Symbol.iterator] === "function"); 
    //输出:true
    console.log(map[Symbol.iterator]); 
    //输出:function entries() { ... }
    
    • 原生具备遍历器的对象
      • 数组、Map集合、Set集合、字符串、arguments和 NodeList(节点列表)。
      • 对象(Object)默认是不可遍历的
      • 我们可以通过Object.keys()、Object.values()和Object.entries() 方法把对象变成数组,使其拥有遍历器
      • 或者直接为对象添加Symbol.iterator 属性来自定义遍历器。
    const obj = {
        name: "Tom",
        age: 19
    }
    console.log(typeof Object.entries(obj)[Symbol.iterator] === "function"); 
    //输出:true
    console.log([...Object.entries(obj)]); 
    //输出:[["name", "Tom"],["age", 19]]
    
    const obj = {
        name: "Tom",
        age: 19,
        [Symbol.iterator]() {
            let data = [],
                i = 0;
            for (let k in this) {
                if (this.hasOwnProperty(k)) {
                    data.push(Array.of(k, this[k]));
                }
            }
            return {
                next() {
                    let done = i >= data.length;
                    let value = !done ? data[i++] : undefined;
                    return {
                        done: done,
                        value: value
                    }
                }
            }
        }
    }
    console.log([...obj]); 
    //输出:[["name", "Tom"],["age", 19]]
    
    • 调用遍历器

      • 当我们去遍历拥有遍历器的对象的时候,系统就会自动去调用对象默认遍历器的接口。没有遍历器接口的对象不能被遍历。
    • for…of 循环

      • 我们知道,遍历器内部的next() 方法,每调用一次只会返回当前成员的信息
      • 而for…of循环将持续调用next() 方法直到返回对象的done 属性的值为 true。
    const arr = ["A", "B", "C"];
    const map = new Map().set("name", "Tom").set("age", 19);
    const str = "love";
    
    for (let v of arr) {
        console.log(v); 
        //输出:A B C
    }
    
    for (let [v, i] of map) {
        console.log(v + ":" + i); 
        //输出:name:Tom age:19
    }
    
    for (let v of str) {
        console.log(v); 
        //输出:l o v e
    }
    
    • 展开运算符
      • 如果我们想把非数组可遍历对象的所有成员填充到一个数组中,最方便的方法是使用展开运算符(…)
      • 展开运算符会触发默认的遍历器取得所有的值,然后按照取得顺序依次插入到数组中。
    console.log([...new Set([1, 2, 3])]) ;
    //输出:[1, 2, 3]
    console.log([1, ...new Set([2, 3]), ...
            "love";
        ]) 
    //输出:[1, 2, 3, "l", "o", "v", "e"]
    
    • ES6中,由于数组的遍历会调用遍历器接口,所以任何接受数组作为参数的场合,其实都调用了遍历器。例如Array.from()方法、Set()、Map()、解构赋值等等。
    console.log(Array.from(new Set([1, 2, 3]))); 
    //输出:[1, 2, 3]
    let [a, b] = new Set([1, 2]);
    console.log(a + "," + b); 
    //输出:1,2
    
  • 相关阅读:
    Spring3:AOP
    Spring2:bean的使用
    Spring1:Spring简介、环境搭建、源码下载及导入MyEclipse
    Vue.js——60分钟组件快速入门(上篇)
    vue父子组件嵌套的时候遇到
    Vue.js——60分钟快速入门
    [Vue warn]: Cannot find element: #app
    关于RabbitMQ以及RabbitMQ和Spring的整合
    spring集成多个rabbitMQ
    RabbitMQ-从基础到实战(5)— 消息的交换(下)
  • 原文地址:https://www.cnblogs.com/SharkJiao/p/13626214.html
Copyright © 2011-2022 走看看