Mengapa (“foo” === String baru (“foo”)) bernilai false di JavaScript?

98

Saya akan mulai menggunakan === (tiga kali lipat sama, perbandingan ketat) sepanjang waktu ketika membandingkan nilai string, tapi sekarang saya menemukannya

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

salah, dan sama dengan ini:

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

Tentu saja:

f == g; // true

Jadi, apakah disarankan untuk selalu menggunakan == untuk perbandingan string, atau selalu mengonversi variabel menjadi string sebelum membandingkan?

Michael Butler
sumber
6
Mungkin karena itu fooadalah string murni dan new String("foo")merupakan Objek String
Danilo Valente
6
Disarankan untuk tidak membuat string dengan new String(Sama sekali tidak berguna) daripada menggunakan==
Esailija
2
Mengapa ada orang yang ingin menggunakan konstruksi seperti new String("foo")di Javascript? Saya belum pernah melihat kode seperti itu dalam kode yaitu jQuery ...
Robert Koritnik
2
Anda dapat menggunakan String(obj)untuk mengonversi string dalam kotak menjadi string primitif setelah Anda menerima parameter "string". ("foo" === String(new String("foo"))) === true
OrangeDog

Jawaban:

126

"foo"adalah string primitif . (konsep ini tidak ada di C # atau Java)

new String("foo") adalah objek string berkotak.

The ===Operator berperilaku berbeda pada primitif dan objek .
Saat membandingkan primitif (dari tipe yang sama), ===akan mengembalikan nilai true jika keduanya memiliki nilai yang sama.

Saat membandingkan objek, ===akan mengembalikan nilai true hanya jika mereka merujuk ke objek yang sama (membandingkan dengan referensi). Jadi new String("a") !== new String("a"),.

Dalam kasus Anda, ===mengembalikan salah karena operan memiliki tipe yang berbeda (satu primitif dan yang lainnya adalah objek).


Primitif bukanlah objek sama sekali.
The typeofOperator tidak akan kembali "object"untuk primitif.

Saat Anda mencoba mengakses properti primitif (menggunakannya sebagai objek), bahasa Javascript akan mengotakkannya ke objek, membuat objek baru setiap saat. Ini dijelaskan dalam spesifikasi .

Inilah mengapa Anda tidak dapat menempatkan properti pada primitif:

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

Setiap kali Anda menulis x.property, objek kotak yang berbedaString dibuat.

SLaks
sumber
33
+1 typeof "foo"; // "string",typeof new String("foo"); // "object"
Sampson
1
Menarik, saya pikir string adalah objek di JS.
Cameron Martin
1
@Sarfraz: Hampir semuanya. Jangan lupa tentang nulldan undefined.
2
if( Object(a) !== a ) { //it's a primitive }
Esailija
1
Java memang memiliki primitif / .Net tidak
Marcelo De Zen
34

Menggunakan === ,

  • sebuah Objek tidak pernah sama dengan apapun kecuali referensi lain untuk dirinya sendiri.

  • primitif sama jika dibandingkan dengan primitif lain jika jenis dan nilainya sama.


sumber
3
new String("foo") === new String("foo")adalah false:-P
Rocket Hazmat
10

The newkata adalah seorang penjahat di sini ( seperti biasa , mungkin saya katakan) ...

Saat Anda menggunakan new, Anda secara eksplisit mengungkapkan keinginan Anda untuk bekerja dengan objek . Ini mungkin mengejutkan bagi Anda, tetapi ini:

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

... akan memberimu kekuatan false . Sederhana saja: perbandingan bukanlah bagian dalam objek, tetapi referensi objek. Dan mereka, tentu saja, tidak sama, karena dua objek berbeda diciptakan.

Apa yang mungkin ingin Anda gunakan adalah konversi :

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

... dan itu akan memberi Anda, seperti yang diharapkan, truesebagai hasilnya, sehingga Anda dapat bersukacita dan sejahtera dengan rekan Anda foosselamanya. )

raina77ow
sumber
2
pertanyaan singkat tentang penggunaan ini. Anda memanggil String (konstruktor?) Tanpa kata kunci 'baru'. Bukankah ini berarti Anda akan mencemari ruang lingkup dengan properti apa pun yang ditetapkan dalam konstruktor String? Atau apakah itu tidak terjadi karena konstruktornya adalah kode asli? Dengan kata lain, misalkan fungsi String berisi "this.a = 1;" - itu berarti fungsi / objek Anda sekarang akan memiliki properti a = 1.
Michael Butler
Saya kira (tetapi tidak dapat mengatakan dengan pasti) masing-masing fungsi 'konstruktor tinju' pertama kali memeriksa konteksnya - dan jika itu bukan 'yang baru' (yaitu, objek prototipe), beralih ke metode konversi segera. Dalam kasus String itu akan menjadi toString()metode, misalnya.
raina77ow
4

fooadalah string murni dan new String("foo")merupakan Objek String

Danilo Valente
sumber
2

Dari node.js REPL ("node" pada baris perintah jika diinstal):

> "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'
mda
sumber