js 数组:
var a = [{name:'huge',age:23},{name:'lee',age:24}]; var b = [{name:'huge',age:23},{name:'lee',age:24}];
两个一模一样的数组,用underscore的取交集函数,结果为[]。 为什么呢?
闭关修行中......
underscore取交集是取引用的交集吧
var a = {name:'huge',age:23}; var b = {name:'huge',age:23};
注意 a !== b;
因为引用的不是同一块地址噢
这个不是underscore的问题,是你对javascript的数据类型的理解不够。 对象是属于引用类型,不是值类型,所以两个对象相等,通常是指他们指向同一个位置。
javascriptvar aa = { name: 'aa', age: '89' } // 上面是创建了一个对象,并返回这个对象的引用(类似于C语言的指针),它其实是个类似于物理地址的东西。 var bb = { name: 'aa', age: '89' } // 这个bb虽然看起来和aa的一样,但是创建这个对象的时候,它是使用的另一块存储空间,即返回的引用是不一样的 console.log(aa === bb); // false
javascript
var aa = { name: 'aa', age: '89' } // 上面是创建了一个对象,并返回这个对象的引用(类似于C语言的指针),它其实是个类似于物理地址的东西。 var bb = { name: 'aa', age: '89' } // 这个bb虽然看起来和aa的一样,但是创建这个对象的时候,它是使用的另一块存储空间,即返回的引用是不一样的 console.log(aa === bb); // false
_.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);
可以根据需要自行删减代码。
underscore取交集是取引用的交集吧
var a = {name:'huge',age:23};
var b = {name:'huge',age:23};
注意
a !== b;
因为引用的不是同一块地址噢
这个不是underscore的问题,是你对javascript的数据类型的理解不够。
对象是属于引用类型,不是值类型,所以两个对象相等,通常是指他们指向同一个位置。
问题就出在这个contains上,包含比较的是引用,不是单纯的值。
_.intersection求交集不是深比较,所以只能传递基本类型的数据,不能传递对象作为参数哦!
拉个angularjs的equals代码给你瞅瞅,比较两个对象是否相等。深比较,里面还有递归,代码很长,因为它所有的情况都考虑到了。
有了这个方法就可以实现取对象的交集了。
可以根据需要自行删减代码。