Можно ли улучшить проверки этого типа с помощью «объекта»? - PullRequest
3 голосов
/ 17 февраля 2011
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!)

Ответы [ 3 ]

1 голос
/ 18 февраля 2011

Вторая проверка не совсем такая же, как первая, нет, просто потому, что JavaScript слабо типизирован, поэтому, по крайней мере, рассмотрим ".toString() эффект", как и другие.Например, они потерпят неудачу при первой проверке, но передадут вторую:

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

Или, немного проще (показывает случай, который вы можете рассмотреть ... но это проходит обе проверки):

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

Одним из исправлений было бы сделать проверку типа и с помощью === , который является оператором строгого сравнения , вы также получаете проверку типа ...но я не полностью уверен, что это то, что вам нужно, поскольку текущая проверка явно "не объект".

1 голос
/ 18 февраля 2011

Взгляните на 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 , чтобы увидеть остальные функции, используемые этой.

Это легко пропуститьнекоторые крайние случаи, поэтому я бы порекомендовал использовать хорошо протестированный код, такой как этот, вместо того, чтобы заново изобретать колесо.

1 голос
/ 18 февраля 2011

это не то же самое.
вот пример, чтобы понять, почему:

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

ваши два, если утверждения не являютсято же самое по очевидной причине.
вы могли бы "улучшить" проверку типа, используя оператор instanceof для соответствия потребностям тура:

if ((typeof a !== "object" || a instanceof Number || a instanceof String) &&
    (typeof b !== "object" || b instanceof Number || b instanceof String))
    return a == b;
...