Tại sao (“foo” === new String (“foo”)) đánh giá là false trong JavaScript?


98

Tôi sẽ bắt đầu sử dụng === (ba bằng, so sánh chặt chẽ) mọi lúc khi so sánh các giá trị chuỗi, nhưng bây giờ tôi thấy rằng

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

là false và tương tự với điều này:

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

Tất nhiên:

f == g; // true

Vì vậy, có nên luôn sử dụng == để so sánh chuỗi hay luôn chuyển đổi các biến thành chuỗi trước khi so sánh không?


6
Có lẽ vì foolà chuỗi tinh khiết và new String("foo")là đối tượng String
Danilo Valente


6
Đó là khuyến cáo không để tạo ra chuỗi với new String(hoàn toàn vô nghĩa) thay vì sử dụng==
Esailija

2
Tại sao mọi người lại muốn sử dụng cấu trúc như new String("foo")trong Javascript ngay từ đầu? Tôi chưa bao giờ nhìn thấy mã ví dụ trong mã ví dụ jQuery ...
Robert Koritnik

2
Bạn có thể sử dụng String(obj)để chuyển đổi một chuỗi đóng hộp thành chuỗi nguyên thủy sau khi bạn nhận được tham số "chuỗi" của mình. ("foo" === String(new String("foo"))) === true
OrangeDog

Câu trả lời:


126

"foo"là một chuỗi nguyên thủy . (khái niệm này không tồn tại trong C # hoặc Java)

new String("foo") là đối tượng chuỗi đóng hộp.

Các ===nhà điều hành xử khác nhau trên nguyên thủy và các đối tượng .
Khi so sánh các giá trị gốc (cùng kiểu), ===sẽ trả về true nếu cả hai đều có cùng giá trị.

Khi so sánh các đối tượng, ===sẽ chỉ trả về true nếu chúng tham chiếu đến cùng một đối tượng (so sánh bằng cách tham chiếu). Vì vậy new String("a") !== new String("a"),.

Trong trường hợp của bạn, ===trả về false vì các toán hạng thuộc các kiểu khác nhau (một là nguyên thủy và kia là đối tượng).


Nguyên thủy hoàn toàn không phải là đối tượng.
Các typeofnhà điều hành sẽ không trở lại "object"cho nguyên thủy.

Khi bạn cố gắng truy cập một thuộc tính của nguyên thủy (sử dụng nó như một đối tượng), ngôn ngữ Javascript sẽ đóng hộp nó vào một đối tượng, tạo một đối tượng mới mỗi lần. Điều này được mô tả trong thông số kỹ thuật .

Đây là lý do tại sao bạn không thể đặt các thuộc tính trên nguyên thủy:

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

Mỗi lần bạn viết x.property, một đối tượng đóng hộp khác nhauString sẽ được tạo ra.


33
+1 typeof "foo"; // "string",typeof new String("foo"); // "object"
Sampson

1
Thật thú vị, tôi nghĩ rằng chuỗi là các đối tượng trong JS.
Cameron Martin

1
@Sarfraz: Hầu hết mọi thứ. Đừng quên về nullundefined.

2
if( Object(a) !== a ) { //it's a primitive }
Esailija

1
Java làm có nguyên thủy / Net không
Marcelo De Zen

34

Sử dụng ===,

  • một Đối tượng không bao giờ bằng bất cứ thứ gì ngoại trừ một tham chiếu khác đến chính nó.

  • một nguyên thủy bằng khi so sánh với một nguyên thủy khác nếu kiểu và giá trị của chúng giống nhau.


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

10

Các newtừ là một tên tội phạm ở đây ( như thường lệ , tôi có thể nói) ...

Khi bạn sử dụng new, bạn thể hiện rõ ràng mong muốn làm việc với đối tượng . Nó có thể gây ngạc nhiên cho bạn, nhưng điều này:

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

... sẽ mang lại cho bạn một sự hùng mạnh false. Thật đơn giản: so sánh không phải là bên trong của đối tượng, mà là tham chiếu của đối tượng. Và tất nhiên, chúng không bằng nhau, vì hai đối tượng khác nhau được tạo ra.

Những gì bạn có thể muốn sử dụng là chuyển đổi :

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

... và điều đó sẽ mang lại cho bạn, như mong đợi true, để bạn có thể vui mừng và thịnh vượng với sự bình đẳng của mình foosmãi mãi. )


2
câu hỏi nhanh về việc sử dụng cái này. Bạn đang gọi String (một hàm tạo?) Mà không có từ khóa 'mới'. Điều này không có nghĩa là bạn sẽ làm ô nhiễm phạm vi với bất kỳ thuộc tính nào được gán trong hàm tạo chuỗi? Hay điều đó không xảy ra vì hàm tạo là mã gốc? Nói cách khác, giả sử hàm String chứa "this.a = 1;" - điều đó có nghĩa là hàm / đối tượng của bạn bây giờ sẽ có thuộc tính a = 1.
Michael Butler

Tôi cho rằng (nhưng không thể nói chắc chắn) mỗi hàm 'hàm tạo quyền anh' trước tiên sẽ kiểm tra ngữ cảnh của nó - và nếu nó không phải là 'hàm mới' (tức là đối tượng nguyên mẫu), hãy chuyển sang phương thức chuyển đổi ngay lập tức. toString()Ví dụ trong trường hợp Chuỗi sẽ là phương thức.
raina77ow


2

Từ REPL của node.js ("nút" trên dòng lệnh nếu được cài đặt):

> "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'
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.