Примитивы и эквивалент обертки объектов в JavaScript
РЕДАКТИРОВАТЬ: Исходя из отзывов каждого, оригинальная версия этого вопроса больше связана с дизайном, а не со стандартами. Делать более ТАК дружелюбным.
Оригинал:
Следует ли считать примитив JS "эквивалентным" объектно-ориентированной версии этого примитива в соответствии со стандартами ECMA?
Пересмотренный вопрос
Существует ли универсальное соглашение о том, как сравнивать примитивные объекты в текущем JavaScript?
var n = new Number(1),
p = 1;
n === p; // false
typeof n; // "object"
typeof p; // "number"
+n === p; // true, but you need coercion.
РЕДАКТИРОВАТЬ:
Как прокомментировал @Pointy, спецификация ECMA (262, S15.1.2.4) описывает Number.isNaN()
метод, который ведет себя следующим образом:
Number.isNaN(NaN); // true
Number.isNaN(new Number(NaN)); // false
Number.isNaN(+(new Number(NaN))); // true, but you need coercion.
Видимо, оправдание такого поведения состоит в том, что isNaN
вернусь true
ЕСЛИ аргумент приводит к NaN
, new Number(NaN)
непосредственно не принуждает основываться на том, как родной isNaN
работает.
Кажется, что прирост производительности и хитрость в преобразовании типов и т. Д. Прямого использования нативных объектных оберток в отличие от примитивов перевешивает смысловые преимущества на данный момент.
1 ответ
Короткий ответ на ваш вопрос - нет, нет единого мнения о том, как сравнивать значения в JS, потому что вопрос слишком ситуативный; это сильно зависит от ваших конкретных обстоятельств.
Но, чтобы дать какой-то совет / дать более длинный ответ.... объектные версии примитивов являются злом (в смысле "они будут вызывать у вас много ошибок", а не в моральном смысле), и их следует избегать, если это возможно. Поэтому, если у вас нет веских оснований для того, чтобы справиться с обоими, я бы посоветовал вам не учитывать примитивы с объектной оболочкой, а просто придерживаться необработанных примитивов в своем коде.
Кроме того, если вы не учитываете обернутые примитивы, это должно исключить необходимость в вас даже использовать метод equals.
* Редактировать *
Только что видел ваш последний комментарий, и если вам нужно сравнить массивы, то встроенный ==
а также ===
не будет сокращать это. Тем не менее, я бы рекомендовал сделать arrayEquals
метод, а не просто equals
метод, поскольку вы избежите большого количества драмы, сохраняя свою функцию как можно более сфокусированной и максимально используя встроенные компараторы JS.
И если вы оберните это в какую-то общую функцию, для удобства:
function equals(left, right) {
if (left.slice && right.slice) { // lame array check
return arrayEquals(left, right);
}
return left == right;
}
Я по-прежнему рекомендую не обрабатывать примитивно-обернутые объекты, если только "дескриптором" вы не заставите свою функцию выдать ошибку, если она пропустит примитивно-обернутый объект. Опять же, поскольку эти объекты будут только доставлять вам неприятности, вы должны стараться избегать их в максимально возможной степени и не оставлять себе возможности вводить плохой код.