Примитивы и эквивалент обертки объектов в 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 работает.

Кажется, что прирост производительности и хитрость в преобразовании типов и т. Д. Прямого использования нативных объектных оберток в отличие от примитивов перевешивает смысловые преимущества на данный момент.

Смотрите этот JSPerf.

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

Я по-прежнему рекомендую не обрабатывать примитивно-обернутые объекты, если только "дескриптором" вы не заставите свою функцию выдать ошибку, если она пропустит примитивно-обернутый объект. Опять же, поскольку эти объекты будут только доставлять вам неприятности, вы должны стараться избегать их в максимально возможной степени и не оставлять себе возможности вводить плохой код.

Другие вопросы по тегам