zoukankan      html  css  js  c++  java
  • js中indexOf()的坑

    indexOf在js中有着重要的作用,可以判断一个元素是否在数组中存在,或者判断一个字符是否在字符串中存在,如果存在返回该元素或字符第一次出现的位置的索引,不存在返回-1。

    例如

    var arr = [1, 2, 3];
    console.log(arr.indexOf(2));    //打印结果为1

    又或者

    var str = "helloworld";
    console.log(str.indexOf("w"));  //打印结果为5

    那么,当想删除某个数组中的某个元素时,常常会这么写

    var arr = [1, 2, 3];
    var idx = arr.indexOf(2);
    arr.splice(idx,1);
    console.log(arr);

    但是,indexOf真的就是好东西吗?看下面的代码。

    var arr = [{name:"racyily",age:22},{name:"susan",age:18}];
    var obj = {name:"susan",age:18};
    console.log(arr.indexOf(obj));  //打印结果为-1

    我们发现obj和arr数组中第1个元素时一样的。但是却返回-1。

    再试试这个

    var arr = [{name:"racyily",age:22},{name:"susan",age:18}];
    var arr2 = arr[1];
    console.log(arr.indexOf(arr2));  //打印结果为1

    这下明白了,就是因为如果数组中存放的是对象或者数组的话,必须是该对象的引用,才可以使用indexOf得到正确的索引值。

    那么,如果想判断一个对象(数组)在一个数组中是否存在(值与元素相等),如何实现呢?

    只能自己写一个方法去实现了。

    最初我是这么写的

    var myIndexOf = function(arr,el){
        for(var i=0;i<arr.length;i++){
            if(JSON.stringify(arr[i]) == JSON.stringify(el)){
                return i;
            }
        }
        return -1;
    }

    上面这段代码实现的原理是将数组中的元素和传进去的对象都通过JSON.stringify()来转成字符串,然后比较两个字符串是否相等,

    这个方法看起来实现了功能,但是一个深深的坑藏在其中。

    因为一旦对象中的字段顺序前后颠倒,就会匹配不到,返回-1(曾经被这个坑深深的伤了心)。

    那么到底怎么规避这样的问题呢,从原理上来说,就是挨个比较对象里每个元素是否都相等。

    看下面代码

    //查找一个对象(数组)是否存在于一个数组中
    function myIndexOf(arr, el) {
        var result = false;
        if (arr instanceof Array && el instanceof Object) {
            for (var i in arr) {
                if(checkLen(arr[i],el)){
                    result = recursiveFunc(arr[i], el);
                }
                if (result) {
                    return i;
                }
            }
            return -1;
        }
        return -1;
    }
    
    //递归调用比较对象每个字段
    var recursiveFunc = function (arr, o) {
        var result = false;
        if (o instanceof Object) {
            if (!(arr instanceof Object)) {
                return false;
            }
            for (var p in arr) {
                if(checkLen(arr[p],o[p])){
                    result = recursiveFunc(arr[p], o[p]);
                    if (!result) {
                        return false;
                    }
                }
            }
            return true;
        }
        else {
            if (arr == o) {
                return true;
            }
            return false;
        }
    }
    
    //判断两个对象长度是否相同。
    var checkLen = function (o1, o2) {
        var count1 = 0,
            count2 = 0;
        if(o1 instanceof Object && o2 instanceof Object){
            for(var i in o1){
                count1++;
            }
            for(var p in o2){
                count2++;
            }
        }
        return count1==count2;
    }

    调第一个方法就可以了,第一个参数是一个数组,第二个参数传一个对象或者数组。

    代码写的不好,见谅,只是提供一个思路。

  • 相关阅读:
    hdu 1203 I NEED A OFFER (0-1背包)
    hdu 2191 悼念512汶川大地震遇难同胞——珍惜现在,感恩生活
    hdu 1284 钱币兑换问题 完全背包
    hdu 1114 Piggy-Bank 完全背包
    hdu 2955 Robberies 0-1背包/概率初始化
    hdu 2602 Bone Collector 背包入门题
    hdu 1002 A+B problem II
    hdu 2689 Sort it
    hdu 1874 畅通工程续 Dijkstra
    hdu 1232 畅通工程 并查集
  • 原文地址:https://www.cnblogs.com/racyily/p/3532393.html
Copyright © 2011-2022 走看看