美文网首页es6相关
被“遗忘”却实用数组Array方法(indexOf、filte

被“遗忘”却实用数组Array方法(indexOf、filte

作者: 108N8 | 来源:发表于2017-04-06 09:33 被阅读515次

    前言:最近学习Vue.js过程中用到了几个很有用但是平时不常见的几个操作数组的方法,这里就总结一下。

    为了更方便的对JS中Array的操作,ES5规范在Array的原型上新增了9个方法
    Array.prototype.indexOf  => 查找元素位置
    Array.prototype.lastIndexOf => 查找元素位置
    Array.prototype.every
    Array.prototype.some => 检测数组中的每一个元素,当callback返回true时就停止遍历,并返回true
    Array.prototype.forEach  => 数组遍历 
    Array.prototype.map  =>  map的作用是对原数组进行加工处理后并将其作为一个新数组返回
    Array.prototype.filter  => 创建一个新的匹配过滤条件的数组。
    Array.prototype.reduce
    Array.prototype.reduceRight
    
    我个人认为是最有用的,很多开发者都会碰到。

    一、 indexOf()

    indexOf()方法返回在该数组中第一个找到的元素位置,如果它不存在则返回-1。(ps:类似字符串的indexOf方法)
    1) 数组内是字符串或者数字

    不使用indexOf时

        var arr = ['apple','banana','pear'];
        var pos = null;
        for(var i=0;i<arr.length;i++){
            if(arr[i] == 'pear'){
                pos = i;
            }
        }
        console.log(pos);   //2
    

    使用indexOf时

    console.log(arr.indexOf("pear"));  //2
    
    2) 数组里面是json(注意:对象在内存中是有自己的地址的)

    例1:

        var arrJson = [];
        var json = {isChecked:false, title:"aaa"};
        arrJson.push(json);
        var json = {isChecked:false, title:"bbb"};
        arrJson.unshift(json);
        arrJson.push(
            {
                isChecked:false,
                title:"ccc"
            }
        );
        console.log(arrJson.indexOf(json));   //0  =>可以找到因为其在内存中地址一样。
        console.log(arrJson.indexOf({isChecked:false, title:"ccc"}));//-1
    

    例2:

        var person = { name: "Datura" };
        var people = [{ name: "Datura" }];
        var morePeople = [person];
        alert(people.indexOf(person)); //-1
        alert(morePeople.indexOf(person)); //0
    

    二、 forEach(callback[thisArg])

    forEach是用来替换for循环的。第一个参数是回调函数,是必选参数,第二个参数是一个对象,用来改变callback中的this指向,是可选参数。
    例1:

    var arr = [1,2,3,4,5,6,7,8,9];
        for(var i=0;i<arr.length;i++){
            console.log(arr[i]);
        }
        //
        arr.forEach(function (item,index) {  //第一个参数是元素,第二个参数是索引
            console.log(item);
        });
    

    例2:

    var arr = ['a','b','c'];
    arr.forEach(function(item,index,obj){
        console.log(item,index,obj);
    })
    ->
    a 0 ["a", "b", "c"]
    b 1 ["a", "b", "c"]
    c 2 ["a", "b", "c"]
    

    从输出的接口可以看出,callback中传入了3个参数item,index,obj 分别表示当前元素、当前位置、数组对象。再看看使用thisArg的情况
    例3:

    var obj = {
       fn:function(a,b){
           console.log(a,b);
       }
    };
    var arr = ['a','b','c'];
    arr.forEach(function(v,i,a){
       this.fn(v,i);
    },obj);
    

    不传thisArgs时,callback中的 this 默认指向window对象,当传递thisArg时,callback中的this就指向了thisArg,因此这个参数的目的就是为了改变回调函数中的this指向

    三、 filter(callback[thisArg])

    filter是过滤的意思,所以这个方法的作用就是返回一个匹配过滤条件的新数组,其接收两个参数callback和thisArg, callback也是回调函数,主要用于对元素进行条件匹配,thisArg和forEach中的thisArg作用一样,在这里就不重复了,看下面.
    例1:

    var arr = [
            {"name":"apple","count":2},
            {"name":"banana","count":1},
            {"name":"orange","count":3},
            {"name":"pear","count":5}
        ];
        var arrNew = [];
        for(var i=0;i<arr.length;i++){
            if(arr[i].name == 'orange'){
                arrNew.push(arr[i]);
            }
        }
        console.log(arrNew);
    
        var arrNew2 = arr.filter(function (item) {
            return item.name === "orange";
        });
        console.log(arrNew2)
    

    例2:

    var arr = ["a","b","a","c"];
    var newArr = arr.filter(function(item){
         return item === "a";
    });
          
    newArr -> ["a","a"]
    

    四、 map(callback[thisArg])

    map()对数组的每个元素进行一定操作(映射)后,会返回一个新的数组,map()是处理服务器返回数据时是一个非常实用的函数。
    例1:

    //不使用map
        var arrFruit = [
            {
                "name":"apple",
                "count":3
            },
            {
                "name":"banana",
                "count":2
            },
            {
                "name":"orange",
                "count":4
            },
            {
                "name":"pear",
                "count":5
            }
        ];
        function getArrNew() {
            var arrNew = [];
            for(var i=0;i<arrFruit.length;i++){
                var item = arrFruit[i];
                item.newData = [item.name,item.count].join("剩余");
                arrNew[i] = item;
            }
            return arrNew;
        }
        console.log(getArrNew());
        function getArrNew2() {
            return arrFruit.map(function (item,index) {
                item.newData = [item.name,item.count].join("剩余");
                return item;
            });
        }
        console.log(getArrNew2());
    

    例2:

    var arr = [
       {w:10,h:10}, //定义长和宽
       {w:15,h:20},
       {w:12,h:12}
    ];
    var newArr = arr.map(function(item){
       //根据长宽计算出面积并赋值给新属性area 
       item.area = item.w * item.h;
       return item;
    });
    newArr[0] - > {w: 10, h: 10, area: 100}
    

    可以看出,newArr返回的是增加了area属性的对象数组。这个方法非常实用,一般情况下,当一个ajax请求返回时,我们都要对其结果集进行过滤和校验等操作,这时map就派上用场了。我们再看看如果对map进行兼容性扩展:
    例3:

    if(!Array.prototype.map) {
       Array.prototype.map = function (callback, thisArg) {
           var temp = [];
           for (var i = 0; i < this.length; i++) {
               var newItem = callback.call(thisArg,this[i]);
               temp.push(newItem); //将callback返回的新元素压入temp中
           }
           return temp;
       }
    }
    

    五、 reduce(callback[initialValue])

    reduce()可以实现一个累加器的功能,将数组的每个值(从左到右)将其降低到一个值。
    说实话刚开始理解这句话有点难度,它太抽象了。
    场景: 统计一个数组中有多少个不重复的单词 。
    例1:

        //不使用reduce时
        var arr = ["apple","orange","apple","orange","pear","orange"];
        function getWordCnt(){
            var obj = {};
            for(var i=0;i<arr.length;i++){
                var item = arr[i];
                obj[item] = (obj[item] +1 ) || 1;
            }
            return obj;
        }
       // console.log(getWordCnt());
    

    让我先解释一下我自己对reduce的理解。reduce(callback, initialValue)会传入两个变量。回调函数(callback)和初始值(initialValue)。假设函数它有个传入参数,prev和next,index和array。prev和next你是必须要了解的。

    一般来讲prev是从数组中第一个元素开始的,next是第二个元素。但是当你传入初始值(initialValue)后,第一个prev将是initivalValue,next将是数组中的第一个元素。
    比如
    例2:

        var arr = ["apple","orange"];
        function noPassValue(){
          return arr.reduce(function(prev,next){
            console.log("prev:",prev);
            console.log("next:",next);
    
            return prev + " " +next;
          });
        }
        function passValue(){
          return arr.reduce(function(prev,next){
            console.log("prev:",prev);
            console.log("next:",next);
    
            prev[next] = 1;
            return prev;
          },{});
        }
        //console.log(noPassValue());
    
        console.log(passValue());
    

    例3:

    var arr = [1,2,3,4];
    var newArr = arr.reduce(function(previousValue, currentValue, currentIndex, array){
        console.log(previousValue, currentValue,currentIndex);
        return previousValue + currentValue;
    },100);
    
    100 1 0
    101 2 1
    103 3 2
    106 4 3
    
    newArr -> 110
    

    从运行结果看,initialValue参数指定了previousValue的初始值,更重要的是,这次数组是从第1个位置开始遍历,而不再是从第2个位置开始了。 现在回过头来,对照这两个例子,我相信你一定能够理解reduce的作用了。下面对于reduce的扩展会巩固你对reduce的理解:
    例4:
    if(!Array.prototype.reduce) {
    Array.prototype.reduce = function (callback, initialValue) {
    var previousValue = initialValue || this[0];//如果不指定intialValue,则默认为数组的第一个元素
    //如果不指定initialValue,i从1开始遍历,否则就从0开始遍历
    for (var i = initialValue?0:1; i < this.length; i++) {
    //previousValue 累加每一次返回的结果
    previousValue += callback(previousValue, this[i],i,this.toString());
    }
    return previousValue;
    }
    }

    ####六、 reduceRight(callback[initialValue])
    reduce的作用完全相同,唯一的不同是,reduceRight是从右至左遍历数组的元素。
    ####七、 some(callback[thisArg])
    ome是`某些、一些`的意思,因此,some的作用是检测数组中的每一个元素,当callback返回true时就停止遍历,并返回true,这样的描述似乎有些抽象,看代码,一切尽在代码中:
    **例1:**
    

    var arr = [ 1, 2, 3, 4];
    var result = arr.some( function( item, index, array ){
    console.log( item, index, array);
    return item > 2;
    });
    ->
    1 0 [1, 2, 3, 4]
    2 1 [1, 2, 3, 4]
    3 2 [1, 2, 3, 4]

    restule -> true

    从运行结果看,some检测整个数组,只要当arr中有一个元素符合条件item>2 就停止检测和遍历,并返回true,以表示检测到目标。这和我们在for循环中使用break语言的作用有点类似,这会儿你应该明白some的作用了吧! 下面对于some的扩展会有助于你对some的理解:
    **例2:**
    

    if(!Array.prototype.some) {
    Array.prototype.some = function (callback, thisArg) {
    for (var i = 0; i < this.length; i++) {
    if(callback.call(thisArg,this[i],i,this.toString())){

               return true; //检测到callback返回true,跳出循环,并返回true
           }
        }
        return false; //一个符合条件的都没有检测到,返回false
    }
    

    }

    ####八、 every(callback[thisArg])
    every是`每一个`的意思,相比some来讲,every对元素的检测应该更加严格,那every到底是干什么的呢,看代码就知道了:
    **例1:**
    

    var arr = [ 1, 2, 3, 4];
    var result = arr.every( function( item, index, array ){
    console.log( item, index, array );
    return item < 3;
    });

    1 0 [1, 2, 3, 4]
    2 1 [1, 2, 3, 4]
    3 2 [1, 2, 3, 4]

    result -> false

    从运行结果看,当检测第3个元素时,item<2为false, 停止检测,并返回false, 这说明every在检测元素时,要求每一个元素都要符合条件item<3,如果有一个不符合就停止检测,并返回false,(ps:你可以测试item<5时的运行结果,返回值一定是true). 那every到底有什么用武之地呢? 当一个for循环使用了break语句后,我们想知道for循环是否正常的执行完时, 我们一般会通过检测for中的索引i==arr.length来判断,因此every的作用就体现在这里。 我们再看看对于every的扩展:
    **例2:**
    

    if(!Array.prototype.every) {
    Array.prototype.every = function (callback, thisArg) {
    for (var i = 0; i < this.length; i++) {
    if(!callback.call(thisArg,this[i],i,this.toString())){
    return false; //检测到不符合条件的元素,跳出循环,并返回false
    }
    }
    return true; //所有元素都符合条件,返回true
    }
    }

    ####九.  forEach 与map的区别:
    高级浏览器支持forEach方法
    语法:forEach和map都支持2个参数:一个是回调函数(item,index,list)和上下文;
    forEach:用来遍历数组中的每一项;这个方法执行是没有返回值的,对原来数组也没有影响;
    数组中有几项,那么传递进去的匿名回调函数就需要执行几次;
    每一次执行匿名函数的时候,还给其传递了三个参数值:数组中的当前项item,当前项的索引index,原始数组input;
    理论上这个方法是没有返回值的,仅仅是遍历数组中的每一项,不对原来数组进行修改;但是我们可以自己通过数组的索引来修改原来的数组;
    forEach方法中的this是ary,匿名回调函数中的this默认是window;
    **例1:**
    

    var ary = [12,23,24,42,1];
    var res = ary.forEach(function (item,index,input) {
    input[index] = item*10;
    })
    console.log(res);//-->undefined;
    console.log(ary);//-->会对原来的数组产生改变;

    map: 和forEach非常相似,都是用来遍历数组中的每一项值的,用来遍历数组中的每一项;
    区别:map的回调函数中支持return返回值;return的是啥,相当于把数组中的这一项变为啥(并不影响原来的数组,只是相当于把原数组克隆一份,把克隆的这一份的数组中的对应项改变了);
    不管是forEach还是map 都支持第二个参数值,第二个参数的意思是把匿名回调函数中的this进行修改。
    **例2:**
    

    var ary = [12,23,24,42,1];
    var res = ary.map(function (item,index,input) {
    return item*10;
    })
    console.log(res);//-->[120,230,240,420,10];
    console.log(ary);//-->[12,23,24,42,1];

    [完...]()

    相关文章

      网友评论

        本文标题: 被“遗忘”却实用数组Array方法(indexOf、filte

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