Почему ( "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'