if (typeof a !== "object" && typeof b !== "object") {
return a == b;
}
... // check pairwise equality of object a & b using `for in`
与
相同if (typeof a !== "object") {
return a == b;
}
是否有b
typeof b === "object"
会改变语义?
我应该注意哪些可怕的边缘情况? object
和native type
之间的比较具有非直观的布尔相等或不平等?包括浏览器中的任何错误(我的意思是你的IE6!)
答案 0 :(得分:1)
它不一样。
这是一个理解原因的例子:
var a = "a string";
var b = new String("a string");
console.log(typeof a);//"string" !== "object"
console.log(typeof b);//"object" === "object"
console.log('"' + a + '" ' + (a==b?"==":"!=") + ' "' + b + '"');
数字可能会发生同样的事情:
var a = 1;
var b = new Number(1);
由于显而易见的原因,你的两个if语句不一样
您可以使用instanceof
运算符来“改善”您的类型检查:
if ((typeof a !== "object" || a instanceof Number || a instanceof String) &&
(typeof b !== "object" || b instanceof Number || b instanceof String))
return a == b;
答案 1 :(得分:1)
第二次检查不是完全与第一次检查相同,不是,因为JavaScript是弱类型的,所以至少考虑“.toString()
效果”,以及其他。例如,这些将在第一次检查时失败,但在第二次检查中失败:
var a = "[object Object]";
var b = {};
或者,更简单一点(显示您可能需要考虑的情况......但这会通过两项检查):
var a = 0;
var b = "0";
一个修复方法是使用===
which is a strict comparison operator进行值和类型检查,您也可以进行类型检查......但我不是完全确定这就是你所追求的,因为当前的检查显然是“不是一个对象”。
答案 2 :(得分:1)
从isEqual查看Underscore.js。它“执行两个对象之间的优化深度比较,以确定它们是否应被视为相等。”它适用于所有类型的变量。这就是它的实现方式:
// Perform a deep comparison to check if two objects are equal.
_.isEqual = function(a, b) {
// Check object identity.
if (a === b) return true;
// Different types?
var atype = typeof(a), btype = typeof(b);
if (atype != btype) return false;
// Basic equality test (watch out for coercions).
if (a == b) return true;
// One is falsy and the other truthy.
if ((!a && b) || (a && !b)) return false;
// Unwrap any wrapped objects.
if (a._chain) a = a._wrapped;
if (b._chain) b = b._wrapped;
// One of them implements an isEqual()?
if (a.isEqual) return a.isEqual(b);
// Check dates' integer values.
if (_.isDate(a) && _.isDate(b)) return a.getTime() === b.getTime();
// Both are NaN?
if (_.isNaN(a) && _.isNaN(b)) return false;
// Compare regular expressions.
if (_.isRegExp(a) && _.isRegExp(b))
return a.source === b.source &&
a.global === b.global &&
a.ignoreCase === b.ignoreCase &&
a.multiline === b.multiline;
// If a is not an object by this point, we can't handle it.
if (atype !== 'object') return false;
// Check for different array lengths before comparing contents.
if (a.length && (a.length !== b.length)) return false;
// Nothing else worked, deep compare the contents.
var aKeys = _.keys(a), bKeys = _.keys(b);
// Different object sizes?
if (aKeys.length != bKeys.length) return false;
// Recursive comparison of contents.
for (var key in a) if (!(key in b) || !_.isEqual(a[key], b[key])) return false;
return true;
};
请参阅Underscore.js source code以查看此功能使用的其他功能。
很容易错过一些边缘情况所以我建议使用经过良好测试的代码,而不是重新发明轮子。