首页 > javascript中,对于元素是对象的数组,用underscore取不到交集?why

javascript中,对于元素是对象的数组,用underscore取不到交集?why

js 数组:

var a = [{name:'huge',age:23},{name:'lee',age:24}];
var b = [{name:'huge',age:23},{name:'lee',age:24}];

两个一模一样的数组,用underscore的取交集函数,结果为[]。
为什么呢?


这个不是underscore的问题,是你对javascript的数据类型的理解不够。
对象是属于引用类型,不是值类型,所以两个对象相等,通常是指他们指向同一个位置。

javascriptvar aa = {
    name: 'aa',
    age: '89'
}
// 上面是创建了一个对象,并返回这个对象的引用(类似于C语言的指针),它其实是个类似于物理地址的东西。

var bb = {
    name: 'aa',
    age: '89'
}
// 这个bb虽然看起来和aa的一样,但是创建这个对象的时候,它是使用的另一块存储空间,即返回的引用是不一样的

console.log(aa === bb); // false

underscore取交集是取引用的交集吧

var a = {name:'huge',age:23};
var b = {name:'huge',age:23};

注意
a !== b;

因为引用的不是同一块地址噢


_.intersection = function (array) {
    if (array == null) return [];
    var result = [];
    var argsLength = arguments.length;
    for (var i = 0, length = array.length; i < length; i++) {
        var item = array[i];
        if (_.contains(result, item)) continue;
        for (var j = 1; j < argsLength; j++) {
            if (!_.contains(arguments[j], item)) break;
        }
        if (j === argsLength) result.push(item);
    }
    return result;
};

_.contains = _.include = function (obj, target) {
    if (obj == null) return false;
    if (obj.length !== +obj.length) obj = _.values(obj);
    return _.indexOf(obj, target) >= 0;
};

问题就出在这个contains上,包含比较的是引用,不是单纯的值。

_.contains([{name:'xxx'}],{name:'xxx'});//false

var s={name:'xxx'};
_.contains([s],s);//true

_.intersection求交集不是深比较,所以只能传递基本类型的数据,不能传递对象作为参数哦!
拉个angularjs的equals代码给你瞅瞅,比较两个对象是否相等。深比较,里面还有递归,代码很长,因为它所有的情况都考虑到了。
有了这个方法就可以实现取对象的交集了。

function isDate(value) {
    return Object.prototype.toString.call(value) === '[object Date]';
}

function isRegExp(value) {
    return Object.prototype.toString.call(value) === '[object RegExp]';
}

function isFunction(value) {
    return typeof value === 'function';
}

function equals(o1, o2) {
    if (o1 === o2) return true;
    if (o1 === null || o2 === null) return false;
    var t1 = typeof o1, t2 = typeof o2, length, key, keySet;
    if (t1 == t2) {
        if (t1 == 'object') {
            if (Array.isArray(o1)) {
                if (!Array.isArray(o2)) return false;
                if ((length = o1.length) == o2.length) {
                    for (key = 0; key < length; key++) {
                        if (!equals(o1[key], o2[key])) return false;
                    }
                    return true;
                }
            } else if (isDate(o1)) {
                if (!isDate(o2)) return false;
                return equals(o1.getTime(), o2.getTime());
            } else if (isRegExp(o1) && isRegExp(o2)) {
                return o1.toString() == o2.toString();
            } else {
                //if (isScope(o1) || isScope(o2) || isWindow(o1) || isWindow(o2) || Array.isArray(o2)) return false;
                keySet = {};
                for (key in o1) {
                    if (key.charAt(0) === '$' || isFunction(o1[key])) continue;
                    if (!equals(o1[key], o2[key])) return false;
                    keySet[key] = true;
                }
                for (key in o2) {
                    if (!keySet.hasOwnProperty(key) &&
                        key.charAt(0) !== '$' &&
                        o2[key] !== undefined && !isFunction(o2[key])) return false;
                }
                return true;
            }
        }
    }
    return false;
}

function intersection(array) {
    var result = [];
    var argsLength = arguments.length;
    for (var i = 0; i < argsLength; i++) {
        var item = array[i];
        if (contains(result, item)) continue;
        for (var j = 1; j < argsLength; j++) {
            if (!contains(arguments[j], item)) break;
        }
        if (j === argsLength) result.push(item);
    }
    return result;
}

function contains(obj, target) {
    if (obj == null) return false;

    var flag = false;
    for (var i = 0; i < obj.length; i++) {
        if (equals(obj[i], target)) {
            flag = true;
        }
    }

    return flag;
}


var a = [{name: 'huge', age: 23}, {name: 'lee', age: 24}];
var b = [{name: 'huge', age: 23}, {name: 'd', age: 24}];

var c = intersection(a, b);
console.log(c);

可以根据需要自行删减代码。

【热门文章】
【热门文章】