Почему ( "foo" === new String ( "foo" )) оценивается как false в JavaScript?

Я собирался начать использовать === (тройное равное, строгое сравнение) все время при сравнении строковых значений, но теперь я обнаружил, что

"foo" === new String("foo")

является ложным, и то же самое:

var f = "foo", g = new String("foo");
f === g; // false

Конечно:

f == g; // true

Так рекомендуется ли всегда использовать == для сравнения строк или всегда преобразовывать переменные в строки перед сравнением?

Ответ 1

"foo" - это примитив строки. (эта концепция не существует на С# или Java)

new String("foo") - строковый объект с строкой.

Оператор === ведет себя по-разному на примитивах и объектах.
При сравнении примитивов (одного и того же типа) === вернет true, если оба они имеют одинаковое значение.

При сравнении объектов === возвращает true, только если они ссылаются на один и тот же объект (сравнивая по ссылке). Таким образом, new String("a") !== new String("a").

В вашем случае === возвращает false, потому что операнды имеют разные типы (один является примитивным, а другой - объектом).


Примитивы вообще не являются объектами.
Оператор typeof не возвращает "object" для примитивов.

Когда вы пытаетесь получить доступ к свойству примитива (используя его как объект), язык Javascript будет привязывать его к объекту, создавая новый объект каждый раз. Это описано в спецификации.

Вот почему вы не можете поместить свойства в примитивы:

var x = "a";
x.property = 2;
alert(x.property) //undefined

Каждый раз, когда вы пишете x.property, создается отдельный объект String.

Ответ 2

Используя ===,

  • Объект никогда не равен чему-либо, кроме другой ссылки на себя.

  • примитив равен по сравнению с другим примитивом, если их тип и значение одинаковы.

Ответ 3

Слово new здесь преступник (как обычно, я могу сказать)...

Когда вы используете new, вы явно выражаете свое желание работать с объектом. Это может быть удивительно для вас, но это:

var x = new String('foo');
var y = new String('foo');
x === y; 

... даст вам мощный false. Это просто: сравниваются не внутренние объекты, а ссылки на объекты. И они, конечно, не равны, поскольку были созданы два разных объекта.

То, что вы, вероятно, хотите использовать, - это преобразование:

var x = String('foo');
var y = String('foo');
x === y;

... и это даст вам, как и ожидалось, true как результат, так что вы можете радоваться и процветать с равным foos навсегда. )

Ответ 4

foo - чистая строка, а new String("foo") - строка объекта

Ответ 5

Из node.js REPL ( "node" в командной строке, если установлен):

> "foo" === (new String("foo")).valueOf()
true
> "foo" === new String("foo")
false
> typeof("foo")
'string'
> typeof(new String("foo"))
'object'
> typeof((new String("foo")).valueOf())
'string'