导航菜单
  • 首页
  • 首页>前端万博manbext备用网址>JavaScript万博manbext备用网址

    JavaScript基础7:数组Arrays常用的迭代方法

    这些新增的方法只有IE9或者Edge及chrome等现代浏览器才支持,IE8及以下就不支持了。不过,老的东西肯定是要被抛弃的,学习新东西是常态。

    技术总是一波接一波更新,所以持续学习是技术人必须的技能。不然很容易被拍死在沙滩上。

    数组迭代方法对每个数组项都要进行操作。

    1、forEach()

    为每个数组元素调用一次函数。这个函数可以称之为“回调函数”。返回值是undefined。不会修改原始数组,但是在callback中可能更改原始数组。

    arr.forEach(callback[,thisArg]);

    callback:

    为数组中每个元素执行的函数,该函数接收三个参数:

  • currentValue 数组中正在处理的当前元素。

  • index  可选 数组中正在处理的当前元素的索引。

  • array  可选  forEach() 方法正在操作的数组。

  • thisArg:

    可选  当执行回调函数时用作 this 的值(参考对象)。

    forEach 方法按升序为数组中含有效值的每一项执行一次callback 函数,那些已删除或者未初始化的项将被跳过。

    以前都是用for循环遍历数组,现在可以改用forEach()了,前提是浏览器支持。

    var arr=['成都','重庆','北京','上海'];
    var city=[];
    for(let i=0;i<arr.length;i++){
        city.push(arr[i]);
    }
    
    //改成forEach()
    arr.forEach(function(value){
        city.push(value);
    })
    function logArray(value,index){
        console.log('arr['+index+']='+value)
    }
    var arr=[1,2,,4,5,,7];
    arr.forEach(logArray); //arr[0]=1 arr[1]=2 arr[3]=4 arr[4]=5 arr[6]=7

    forEach 遍历的范围在第一次调用 callback 前就会确定。调用 forEach 后添加到数组中的项不会被 callback 访问到。如果已经存在的值被改变,则传递给 callback 的值是 forEach遍历到他们那一刻的值。已删除的项不会被遍历到。如果已访问的元素在迭代时被删除了(例如使用 shift()),之后的元素将被跳过。而且,不能中止遍历,除非报错。

    var arr=[1,2,-Infinity,'2',50];
    
    arr.forEach(function(num,index){
    if(num===-Infinity){
    arr.splice(index,2);
    }
    console.log(num); //1,2,-Infinity
    })
    
    arr.forEach(function(num,index){
    if(num===-Infinity){
    arr.splice(index,2,Infinity,10);
    }
    console.log(num); //1,2,-Infinity,10,50
    })

    在DOM中,用querySelectorAll()返回的是NodeList节点集合,并不是真的数组,而是一种类数组。低版本不支持forEach()函数,所以升级浏览器吧。可以不用for循环了。

    var oP=document.querySelectorAll('p');
    console.log(oP); //NodeList(5) [p, p, p, p, p]
    oP.forEach(function(obj,index){
    obj.innerHTML=index;
    });

    具体参考:Array.prototype.forEach()

    2、map()

    和forEach()几乎一样的使用方法,参数都是一样的,差别在于map()函数会返回一个新数组

    var arr=[2,4,8,10];
    var newArr=arr.map(function(x){
        return x/2;
    })
    console.log(newArr); //[1, 2, 4, 5]

    map里面的回调函数也可以不是自定义的函数,可以是现有的内置函数。

    var num=[2,15,'12','a'];
    var newNum=num.map(isNaN); //isNaN是一个函数,所以不能加()。 [false, false, false, true]
    
    var num=['1',2,'2.2e2',2.5e-3];
    var newNum=num.map(Number);//[1, 2, 220, 0.0025]

    但是要注意,有些函数有多个参数,可能会导致问题。

    比如:parseInt(numString, [radix]),如果用这个函数的话,就会把数组的索引值当成了进制数。

    numString:必选项。要转换为数字的字符串。

    radix :  可选项。在 2 和 36 之间的表示 numString 所保存数字的进制的值。如果没有提供,则前缀为 '0x' 的字符串被当作十六进制,前缀为 '0' 的字符串被当作八进制。所有其它字符串都被当作是十进制的。

    parseInt 方法返回与保存在 numString 中的数字值相等的整数。如果 numString 的前缀不能解释为整数,则返回 NaN(而不是数字)。

    var num=[1,2,10,4,5,6,12,16,7];
    var newNum=num.map(parseInt); // [1, NaN, 2, NaN, NaN, NaN, 8, 13, 7]
    parseInt(10,2);// 2
    parseInt('0xffffff',16); //16777215
    parseInt(7,8); //7
    parseInt(2,10);//2

    目前,最新的浏览器,NodeList类数组也不支持map()方法,但是还是可以利用call()方法实现。

    obj1.(method).call(obj2,argument1,argument2)

    call()方法就是把obj1的方法拿给obj2用。argument是obj1方法的参数。

    <label><input type="checkbox" name="hobby" id="c1" value="编程">编程</label>
    <label></label><input type="checkbox" name="hobby" id="c2" checked value="美术">美术</label>
    <label></label><input type="checkbox" name="hobby" id="c3" checked value="阅读">阅读</label>
    <script>
    var oCheckbox=document.querySelectorAll("input:checked"); //NodeList(2) [input#c2, input#c3]
    var values=Array.prototype.map.call(oCheckbox,function(obj){
    return obj.value;
    })
    console.log(values); //["美术", "阅读"]
    </script>

    这里有个动图很好的解释了map()的工作原理,来源于:https://www.w3cplus.com/web/web-tips-15.html

    3、filter()

    filter是过滤,筛选的意思,顾名思义,应该是数组元素挨个进行某个条件测试,然后返回成功通过的新数组

    var newArray = arr.filter(callback(element[, index[, array]])[,thisArg])

    callback

    用来测试数组的每个元素的函数。返回 true 表示该元素通过测试,保留该元素,false 则不保留。

    后面的参数和前面的map()等迭代函数意思一样。

    返回值是一个新的、由通过测试的元素组成的数组,如果没有任何数组元素通过测试,则返回空数组。

    var age=[12,18,25,45,60,17,22];
    var result=age.filter(function(value){
    return value>=18 && value<=45;
    })
    console.log(result); //[18, 25, 45, 22]
    var arr=[2,8,'a','12',-12,null,undefined,,'',NaN];
    
    function myFilter(value){
    return  value!==undefined&&typeof(value)==='number'&&!isNaN(value)&&value!==0;
    }
    var newArr=arr.filter(myFilter);
    console.log(newArr); // [2, 8, -12]

    4、every()

    检测数组内所有元素是否通过测试,全部通过返回true,任何一个不通过,返回false。如果是一个空数组,返回true。返回布尔值。

    感觉就是一竿子打翻一船人啊,或者说一颗老鼠屎坏了一锅汤 :)

    function isBig(value) {
    return value >= 60 && value <= 100;
    }
    var result = [85, 75, 98, 53, 60, 105].every(isBig);
    console.log(result); //false
    
    也可以简写成箭头函数:
    [85, 75, 98, 53, 60, 105].every(value=>value>=60&&value<=100)

    5、some()

    有至少一个数组元素通过了测试,就返回true。返回的是一个布尔值。

  • 如果一个元素满足条件,返回true,且后面的元素不再被检测

  • 所有元素都不满足条件,则返回false

  • 不会改变原始数组

  • 不会对空数组进行检测;数组为空的话,直接返回false

  • function isBiggerThan10(item){
        return item>10;    
    }
    [12,10,8,7,-5].some(isBiggerThan10); //true;

    检查某个元素是否存在:

    var myname=['老赵','小何','小王'];
    function isExit(arr,val){
    return  arr.some(function(value){
    return value===val;
    })
    }
    console.log(isExit(myname,'老赵')); //true

    6、includes()

    确定数组的条目中是否包含某个值,并根据需要返回true或false没有回调函数,只有两个参数。

    ES6的新方法,Edge14及以上才支持。

    arr.includes(valueToFind[,fromIndex])

    注意:比较字符的时候,区分大小写。

    [1, 2, 3].includes(2);     // true
    [1, 2, 3].includes(4);     // false
    [1, 2, 3].includes(3, 3);  // false
    [1, 2, 3].includes(3, -1); // true
    [1, 2, 3].includes(3, -4); // true
    [1, 2, NaN].includes(NaN); // true

    该方法的第二个参数表示搜索的起始位置,默认为0。

    如果fromIndex大于或等于数组的长度,则返回false。将不搜索数组。

    如果FromIndex为负数,则按照array.length + fromIndex先计算。计算出的索引将用作数组中开始搜索valueToFind的位置。如果计算的索引小于或等于-1*array.length,则将搜索整个数组。

    // array length is 3
    // fromIndex is -100// 
    computed index is 3 + (-100) = -97
    var arr = ['a', 'b', 'c'];
    arr.includes('a', -100); // true
    arr.includes('b', -100); // true
    arr.includes('c', -100); // true
    arr.includes('a', -2); // false

    以前查找使用indexOf(),但是不能判断出NaN。

    [NaN].indexOf(NaN);// -1

    现在includes()使用samevaluezero算法来确定是否找到给定的元素。所以可以得到NaN,而且+0,-0,0都当成0,false不能当成0。

    [NaN].includes(NaN);// true
    [-0].includes(0);// true

    如果为了兼容IE9,可以利用some()写一个includes()的简易版。

    const contains = (() =>
    Array.prototype.includes
    ? (arr, value) => arr.includes(value)
    : (arr, value) => arr.some(el => el === value)
    )();
    contains(['foo', 'bar'], 'baz'); // => false

    7、find()

    arr.find(callback(element[, index[, array]])[, thisArg])

    找到第一个符合条件测试的元素,并返回,如果没有找到,返回undefined.

    Edge12及以上支持,IE9不支持。

    const myArr=[1,2,3,4,5,6];
    var v=myArr.find(value=>value>4);
    console.log(v);// 5
    
    const myArr=[1,2,3,4,5,6];
    var v=myArr.find(value=>value>40);
    console.log(v);// undefined

    8、findIndex()

    arr.findIndex(callback(element[, index[, array]])[, thisArg])

    和find()相似,只不过返回的是第一个通过测试的元素的索引值没有返回-1

    const students=[
    {
    id:1,
    s_name:'小王'
    },
    {
    id:2,
    s_name:'小赵'
    },
    {
    id:3,
    s_name:'小李子'
    }
    ]
    var i=students.findIndex(value=>value.id==2);
    console.log(i); //1
    var n=students.findIndex(value=>value.id==5);
    console.log(n); //-1

    数组的方法太多了,有些方法具有相似的功能,但是还是要看几个关键点,功能有什么区别,参数是什么,返回的值是什么,有没有修改原数组等。只有关联起来理解才不会混乱。

    var arr1=[NaN,undefined,null,2,0];
    console.log(arr1.indexOf(NaN)); //-1
    console.log(arr1.includes(NaN)); //true
    console.log(arr1.find(function(value){ //null
    return value===null;
    }));
    console.log(arr1.findIndex(function(value){ //1
    return value===undefined;
    }))
    console.log(arr1.filter(function(value){ // [null, 2, 0]
    return value>=0;
    }))

    9、reduce()

    reduce() 方法对数组中的每个元素执行一个回调函数中提供的reducer函数(升序执行),将其结果汇总为单个返回值。

    arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])

    reducer 函数接收4个参数:

  • Accumulator (acc) (累计器) 累计器累计回调的返回值; 它是上一次调用回调时返回的累积值,或initialValue(初始值)。

  • Current Value (cur) (当前值) 数组中正在处理的元素。

  • Current Index (idx) (当前索引)  数组中正在处理的当前元素的索引。 如果提供了initialValue,则起始索引号为0,否则为1。

  • Source Array (src) (源数组)  调用reduce()的数组

  •  reducer 函数的返回值分配给累计器,该返回值在数组的每个迭代中被记住,并最后成为最终的单个结果值。

    initialValue 可选 作为第一次调用 callback函数时的第一个参数的值。 如果没有提供初始值,则将使用数组中的第一个元素。 在没有初始值的空数组上调用 reduce 将报错。

    返回函数累计处理的结果.

    回调函数第一次执行时,accumulator 和currentValue的取值有两种情况:如果调用reduce()时提供了initialValue,accumulator取值为initialValue,currentValue取数组中的第一个值;如果没有提供 initialValue,那么accumulator取数组中的第一个值,currentValue取数组中的第二个值。

    注意:如果没有提供initialValue,reduce 会从索引1的地方开始执行 callback 方法,跳过第一个索引。如果提供initialValue,从索引0开始。

    var sum = [0, 1, 2, 3].reduce(function (accumulator, currentValue) {
      return accumulator + currentValue;}, 0); 
      //6
    var initialValue = 0;var sum = [{x: 1}, {x:2}, {x:3}].reduce(function (accumulator, currentValue) {
        return accumulator + currentValue.x;},initialValue)
        console.log(sum) 
        // logs 6
    var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
      function(a, b) {
        return a.concat(b);
      },
      []);
      // flattened is [0, 1, 2, 3, 4, 5]

    数组的方法实在太多,看图:

    array.jpg

    数组全部的方法:MDN:Array

    点赞


    1
    保存到:

    相关文章

    发表评论:

    ◎请发表你卖萌撒娇或一针见血的评论,严禁小广告。

    Top