Чому ("foo" === new String ("foo")) в JavaScript перетворюється на помилковий?


98

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

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

є помилковим, і те ж саме з цим:

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

Звичайно:

f == g; // true

Тож чи рекомендується завжди використовувати == для порівняння рядків або завжди перетворювати змінні в рядки перед порівнянням?


6
Може тому, що fooце чистий рядок і new String("foo")є Об'єктна рядок
Данило Валенте


6
Рекомендується не створювати рядки за допомогою new String(Цілком безглуздо), а не використовувати==
Esailija

2
Чому хтось хотів би new String("foo")в першу чергу використовувати такі конструкції, як у Javascript? Я ніколи не бачив такого коду в коді, тобто jQuery ...
Роберт Коритник

2
Ви можете використовувати String(obj)для перетворення рядок у вікні примітиву, як тільки ви отримали параметр "string". ("foo" === String(new String("foo"))) === true
OrangeDog

Відповіді:


126

"foo"є рядковим примітивом . (ця концепція не існує в C # або Java)

new String("foo") є об'єктом рядка в коробці.

===Оператор поводиться по- різному на примітиви і об'єкти .
Якщо порівнювати примітиви (одного типу), ===повернеться вірно, якщо вони мають однакове значення.

Порівнюючи об'єкти, ===повернеться істинне, лише якщо вони посилаються на один і той же об'єкт (порівнюючи за посиланням). Таким чином, new String("a") !== new String("a").

У вашому випадку ===повертає значення false, оскільки операнди бувають різних типів (один є примітивним, а другий - об'єктом).


Примітиви взагалі не є об’єктами. Оператор не повертає для примітивів.
typeof"object"

Коли ви намагаєтеся отримати доступ до властивості примітиву (використовуючи його як об’єкт), мова Javascript буде вказувати його об'єкту, створюючи новий об'єкт кожного разу. Це описано в специфікації .

Ось чому ви не можете розміщувати властивості на примітивах:

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

Кожен раз , коли ви пишете x.property, різні коробочки Stringоб'єкт створюється.


33
+1 typeof "foo"; // "string",typeof new String("foo"); // "object"
Сампсон

1
Цікаво, що я думав, що рядки - це об'єкти в JS.
Камерон Мартін

1
@Sarfraz: Майже все. Не забувайте про nullі undefined.

2
if( Object(a) !== a ) { //it's a primitive }
Есаїлія

1
У Java є примітиви / .Net не
Marcelo De Zen

34

Використовуючи ===,

  • Об'єкт ніколи не дорівнює нічого, крім іншого посилання на себе.

  • примітив є рівним порівняно з іншим примітивом, якщо їх тип і значення однакові.


3
new String("foo") === new String("foo")це false:-P
Ракета Hazmat

10

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назавжди. )


2
швидке запитання щодо використання цього. Ви називаєте String (конструктор?) Без ключового слова "new". Чи це не означає, що ви забруднити область будь-якими властивостями, призначеними в конструкторі String? Або цього не відбувається, оскільки конструктор - це власний код? Іншими словами, припустимо, що функція String містила "this.a = 1;" - це означає, що ваша функція / об’єкт тепер матиме властивість a = 1.
Майкл Батлер

Я думаю (але не можу сказати точно) кожна з функцій «конструктора боксу» спочатку перевіряє свій контекст - і якщо це не «новація» (тобто об’єкт прототипу), переходить на метод перетворення відразу. У випадку String це був би toString()метод, наприклад.
raina77ow


2

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

> "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'
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.