【问题标题】:Can this type checks with "object" be improved?这种类型的“对象”检查可以改进吗?
【发布时间】:2026-01-30 01:35:02
【问题描述】:
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;
}

是否有 btypeof b === "object" 会改变语义?

我应该注意哪些可怕的边缘情况? objectnative type 之间的比较具有非直观的布尔相等或不相等?包括浏览器中的任何错误(我的意思是你的 IE6!)

【问题讨论】:

  • 这取决于您关心的问题,例如 var a = "[object Object]";var b = {} 在您的第二次检查中会相等,但不是第一次。
  • @NickCraver 哎呀!这是一个可怕的副作用!基本上我担心对象等于这样的东西。
  • @Nick:写在答案中,因为它是:“[object Object]”== {},回答这一行:Is there any b with typeof b === "object" 这会改变语义?
  • 记住 javascript 有自动类型转换 - 如果你愿意,你可以通过 a===b 来解决这个问题
  • @MartinJespersen 我知道我在用类型强制做什么(部分)只是想找到像上面那个可怕的边缘情况。

标签: javascript equals equality typeof type-coercion


【解决方案1】:

第二个检查与第一个检查不同完全,不,仅仅是因为 JavaScript 是弱类型的,所以至少考虑“.toString() 效应”,以及其他。例如,这些将通过第一次检查,但通过第二次:

var a = "[object Object]";
var b = {};

或者,更简单一点(展示一个您可能想要考虑的案例……但这两项检查都通过了):

var a = 0;
var b = "0";

一种解决方法是使用=== which is a strict comparison operator 进行值类型检查,您也可以进行类型检查...但我不是完全 确定这就是你所追求的,因为当前的检查明确地是“不是对象”。

【讨论】:

  • cmon 尼克。至少让我怀疑我知道类型强制的工作原理以及===== 之间的区别;)
  • @Raynos - 请记住,许多其他人都会看到所有答案,实际上我的答案很少全部只针对OP,请不要冒犯:)
  • 我知道,只是觉得有点傲慢。没关系。每个人都需要记住类型强制的恐怖。特别是因为边缘情况是不直观的。
【解决方案2】:

不一样。
这是一个理解原因的示例:

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;

【讨论】:

  • @Raynos:如果您只想检查简单类型,只需检查原型属性是否存在于 a & b 上;)if(!a.prototype && !b.prototype) { return a==b; }
  • @MartinJespersen 我实际上想从 CommonJS 实现 assert.deepEqual,这有点“错误”。
  • @Raynos:在这种情况下,不要吝啬检查...对所有内容都进行 typeofs 处理,完全不要强制
  • @MartinJespersen 规范说诉诸类型强制:)
【解决方案3】:

Underscore.js 看看isEqual。它“在两个对象之间执行优化的深度比较,以确定它们是否应该被视为相等。”它适用于所有类型的变量。这是它的实现方式:

  // 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 以查看该函数使用的其余功能。

很容易错过一些边缘情况,所以我建议使用像这样经过良好测试的代码,而不是重新发明*。

【讨论】:

  • 遥遥领先。我从那个来源获取了我的大部分功能:)。可惜它不满足 CommonJS 规范。
最近更新 更多