Tại sao “,,,” == Array (4) trong Javascript?


119

Khởi động trình thông dịch / bảng điều khiển của bạn và thử so sánh

> ",,," == Array(4)
True

Tại sao? Lúc đầu, tôi nghĩ có thể vì bạn có thể nghĩ về ",,," là một mảng gồm bốn ký tự với lát kết thúc '\ 0', đó có thể là lý do tại sao, nhưng

> "..." == Array(4)

Trả về "Sai". Vậy tại sao? Tôi biết đó là một số kiểu gõ vịt đặc trưng trong Javascript, nhưng tôi chỉ tò mò điều gì nhấn mạnh hành vi này. Lượm lặt điều này từ bài thuyết trình xuất sắc của Zed Shaw ở đây btw .


14
Rất ít ngôn ngữ ngoài C sử dụng dấu chấm hết theo cách mà lập trình viên có thể nhìn thấy được.
Joey

7
Nếu tôi có thể hỏi, điều gì dẫn đến khám phá này?
SomeKittens

1
@SomeKittens Zed Shaw đề cập đến điều này một cách rõ ràng trong video mà tôi đã liên kết đến trong câu hỏi của mình (như một lời chỉ trích về Javascript). Chúc mừng!
ZenLikeThat

5
@SomeKittens này cũng được đề cập trong (khá nổi tiếng) "wat" nói chuyện, cho thấy một số tật trong Ruby và JavaScript destroyallsoftware.com/talks/wat
Cronco

5
Đây là một trong nhiều lý do tốt để luôn sử dụng ===thay vì ==.
wprl

Câu trả lời:


178

Bởi vì toán hạng bên phải được chuyển đổi thành một chuỗi và biểu diễn chuỗi Array(4),,,:

> Array(4).toString()
  ",,,"

Nếu bạn sử dụng hàm tạo mảng và chuyển một số, nó sẽ đặt độ dài của mảng thành số đó. Vì vậy, bạn có thể nói rằng bạn có bốn chỉ mục trống (giống như [,,,]) và biểu diễn chuỗi mặc định của mảng là danh sách được phân tách bằng dấu phẩy gồm các phần tử của nó:

> ['a','b','c'].toString()
  "a,b,c"

Cách so sánh hoạt động được mô tả trong phần 11.9.3 của đặc điểm kỹ thuật . Ở đó bạn sẽ thấy ( x == y):

8. Nếu Kiểu ( x ) là Chuỗi hoặc Số và Kiểu ( y ) là Đối tượng,
trả về kết quả của phép so sánh x == ToPrimitive ( y ).

(mảng là các đối tượng trong JavaScript)

và nếu bạn làm theo ToPrimitivephương pháp này, cuối cùng bạn sẽ thấy rằng nó gọi toString.


2
Được rồi, bây giờ tất cả điều này có ý nghĩa đối với tôi. Cảm ơn.
ZenLikeThat

6
Đến lượt nó, là do các mảng được xâu chuỗi như thể chúng đang sử dụng Array.join(",").
duskwuff -inactive- Ngày

Bạn phải kiên nhẫn đẫm máu để chương trình trong javascript
matcheek


31

Hãy thử sử dụng ===. Khi sử dụng ==trong Javascript, nó sẽ cố ép các biến, do đó dẫn đến các vấn đề như thế này. Bàn điều khiển đang truyền Array(4)đến biểu diễn chuỗi (tức là Array(4).toString), đó là ",,,". Lý do có dấu phẩy là do .toString()hàm thêm chúng để tách các mục trong một mảng.

Xem đoạn mã dưới đây:

document.write( Array(4).toString() );


18

Điều này là do Array(4)khởi tạo một mảng gồm 4 giá trị trống, một ==chuyển đổi ngầm định, vì vậy:

 ",,," == Array(4)

 ",,," == Array(4).toString()

 ",,," == ["", "", "", ""] // note 3 commas for 4 values

 ",,," == ["", "", "", ""].toString()

Tất cả đều giống nhau.

==chuyển đổi kiểu ẩn trước khi so sánh các giá trị, điều này có thể dẫn đến kết quả không thể đoán trước. Sử dụng ===để kiểm tra loại và giá trị.


5

So sánh Mảng với một chuỗi buộc Mảng thành một chuỗi trước khi thực hiện so sánh. Việc ép buộc một Mảng 4 phần tử trống thành một chuỗi sẽ thu được chuỗi chính xác đó.


4

Đầu tiên tôi nghĩ đó là một thứ gì đó giống với "nguyên mẫu" ... nhưng sau một cuộc điều tra nhỏ, tôi đã đưa ra một kết luận đáng buồn ...

Rõ ràng nó là một thứ js nội bộ và tối nghĩa hơn, không có nhiều logic ...

Cứ thử đi

Array(4)==Array(4)

và không có sự ép buộc về các loại cũng ...

Array(4)===Array(4)

và bạn sẽ nhận được FALSE

bạn biết điều đó null==null, null===nullvà thậm chí undefined==undefinedundefined===undefinedtrả về TRUE ... vì vậy ... nó hơi tối nghĩa ...

Array(4)==[,,,] cũng nên đúng


ZEE, Array (4) == [,,,] sẽ không đúng. Nếu chúng ta so sánh đối tượng với nguyên thủy, thì đối tượng sẽ được chuyển thành nguyên thủy. Đó là lý do nó gọi tớiString ().
devsathish

mảng (x) phải là địa chỉ của hàm tạo ... dù sao, trong một hệ thống (đừng bận tâm đến loại hệ thống nào), <identity_X> === <identity_X> sẽ luôn đúng!
ZEE
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.