这种类型可以用“object”进行检查吗?有待改进吗?

发布于 2024-10-17 23:01:39 字数 441 浏览 6 评论 0原文

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;
}

它是否与是否有任何带有 typeof b === "object"b 会改变语义

?有什么我应该注意的可怕的边缘情况吗?具有非直观布尔相等或不相等的对象本机类型之间的比较?包括浏览器中的任何错误(我指的是 IE6!)

if (typeof a !== "object" && typeof b !== "object") {
    return a == b;
}
... // check pairwise equality of object a & b using `for in`

Is it the same as

if (typeof a !== "object") {
    return a == b;
}

Is there any b with typeof b === "object" which would change the semantics?

Are there any horrible edge cases I should be aware of? Comparisons between an object and a native type which have a non-intuitive boolean equality or disequality? Including any bugs in browser (I mean you IE6!)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半山落雨半山空 2024-10-24 23:01:39

第二个检查与第一个检查不太一样,不,只是因为 JavaScript 是弱类型的,所以至少要考虑“.toString() 效果”,如下以及其他人。例如,这些将在第一次检查中失败,但在第二次检查中通过:

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

或者,更简单一点(显示您可能想要考虑的情况......但这通过了两项检查):

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

一个解决方法是执行一个值 并使用 === 进行类型检查 which是一个严格的比较运算符,您也会进行类型检查...但我不完全确定这就是您所追求的,因为当前检查明确“不是对象” ”。

The second check is not quite the same as the first, no, simply because JavaScript is weakly typed so at the very least consider the ".toString() effect", as well as others. For example these would fail the first check, but pass in the second:

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

Or, a bit simpler (showing a case you may want to consider...but this passes both checks):

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

One fix would be to do a value and type check with === which is a strict comparison operator, you get type checking as well...but I'm not entirely sure that's what you're after, since the current check is explicitly "not an object".

ヤ经典坏疍 2024-10-24 23:01:39

不一样。
这里有一个例子来理解为什么:

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;

it's not the same.
here's an example to understand why :

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 + '"');

the same thing can happen for numbers :

var a = 1;
var b = new Number(1);

your two if statements are not the same for the obvious reason.
you could "improve" your type check by using the instanceof operator to suite tour needs :

if ((typeof a !== "object" || a instanceof Number || a instanceof String) &&
    (typeof b !== "object" || b instanceof Number || b instanceof String))
    return a == b;
勿忘初心 2024-10-24 23:01:39

看看 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 源代码 以查看其余部分这个函数使用的函数。

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

Take a look at isEqual from Underscore.js. It "Performs an optimized deep comparison between the two objects, to determine if they should be considered equal." It works for all types of variables. This is how it's implemented:

  // 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;
  };

See the Underscore.js source code to see the rest of the functions used by this one.

It's easy to miss some edge cases so I would recommend using a well tested code like this one instead of reinventing the wheel.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文