ทำไม“ ,,,” == Array (4) ใน Javascript


119

บูตล่าม / คอนโซลของคุณแล้วลองเปรียบเทียบ

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

ทำไม? ตอนแรกฉันคิดว่าอาจจะเป็นเพราะคุณคิดว่า ",,," เป็นอาร์เรย์ของอักขระสี่ตัวที่มีเครื่องหมาย "\ 0" ยกเลิกชิ้นส่วนนั่นอาจเป็นสาเหตุ แต่

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

ส่งคืน "เท็จ" ทำไม? ฉันรู้ว่ามันเป็นการพิมพ์เป็ดที่แปลกประหลาดใน Javascript แต่แค่อยากรู้ว่าอะไรที่เน้นย้ำพฤติกรรมนี้ รวบรวมนี้จากการที่ยอดเยี่ยม Zed ชอว์นำเสนอที่นี่ครับ


14
ภาษาไม่กี่ภาษานอกเหนือจากภาษา C ใช้การสิ้นสุดเป็นศูนย์ในลักษณะที่โปรแกรมเมอร์มองเห็นได้
Joey

7
ถ้าฉันอาจถามว่าอะไรทำให้เกิดการค้นพบนี้
SomeKittens

1
@SomeKittens Zed Shaw กล่าวถึงสิ่งนี้อย่างชัดเจนในวิดีโอที่ฉันเชื่อมโยงไว้ในคำถามของฉัน (เป็นการวิจารณ์ Javascript) ไชโย!
ZenLikeThat

5
@SomeKittens สิ่งนี้ยังถูกกล่าวถึงในการพูดคุย "วัต" (ซึ่งเป็นที่รู้จักกันดี) แสดงนิสัยใจคอใน Ruby และ JavaScript destroyallsoftware.com/talks/wat
Cronco

5
นี่เป็นหนึ่งในหลายเหตุผลที่ดีที่ควรใช้===แทน==เสมอ
wprl

คำตอบ:


178

เนื่องจากตัวถูกดำเนินการด้านขวาถูกแปลงเป็นสตริงและการแสดงสตริงArray(4)คือ,,,:

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

หากคุณใช้ฟังก์ชันตัวสร้างอาร์เรย์และส่งผ่านตัวเลขจะกำหนดความยาวของอาร์เรย์เป็นตัวเลขนั้น ดังนั้นคุณสามารถพูดได้ว่าคุณมีดัชนีว่างสี่รายการ (เช่นเดียวกับ[,,,]) และการแสดงสตริงเริ่มต้นของอาร์เรย์คือรายการองค์ประกอบที่คั่นด้วยจุลภาค:

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

วิธีการทำงานของการเปรียบเทียบอธิบายไว้ในส่วน11.9.3 ของข้อกำหนด คุณจะเห็น ( x == y):

8. ถ้า Type ( x ) เป็น String หรือ Number และ Type ( y ) เป็น Object ให้
ส่งคืนผลลัพธ์ของการเปรียบเทียบx == ToPrimitive ( y )

(อาร์เรย์เป็นวัตถุใน JavaScript)

และถ้าคุณทำตามToPrimitiveวิธีนี้คุณจะพบว่ามันเรียกมันในtoStringที่สุด


2
เอาล่ะตอนนี้ทุกอย่างสมเหตุสมผลสำหรับฉัน ขอบคุณ
ZenLikeThat

6
ซึ่งในที่สุดก็เป็นเพราะอาร์เรย์ stringify Array.join(",")ราวกับว่าพวกเขาใช้
duskwuff -inactive-

คุณต้องเป็นผู้ป่วยเลือดเพื่อตั้งโปรแกรมในจาวาสคริปต์
matcheek


31

ลองใช้===. เมื่อใช้==ใน Javascript มันจะพยายามแคสต์ตัวแปรจึงนำไปสู่ปัญหาเช่นนี้ คอนโซลหล่อArray(4)เพื่อแสดงสตริง (เช่นArray(4).toString) ",,,"ซึ่งเป็น เหตุผลที่มีเครื่องหมายจุลภาคคือ.toString()ฟังก์ชันจะเพิ่มรายการเหล่านี้เพื่อแยกรายการในอาร์เรย์

ดูตัวอย่างด้านล่าง:

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


18

นี่เป็นเพราะArray(4)เริ่มต้นอาร์เรย์ของค่าว่าง 4 ค่าซึ่งเป็นการ==แปลงโดยปริยายดังนั้น:

 ",,," == Array(4)

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

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

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

ล้วนคล้ายกัน.

==ทำการแปลงประเภทโดยนัยก่อนที่จะเปรียบเทียบค่าซึ่งอาจทำให้ได้ผลลัพธ์ที่คาดเดาไม่ได้ ใช้===ตรวจสอบประเภทและค่า


5

การเปรียบเทียบ Array กับสตริงจะบังคับให้ Array กับสตริงก่อนทำการเปรียบเทียบ การบังคับอาร์เรย์ 4 องค์ประกอบที่ว่างเปล่าเข้ากับสตริงจะให้ผลลัพธ์เป็นสตริงที่แน่นอน


4

ตอนแรกฉันคิดว่ามันเป็นของ "ต้นแบบ" ... แต่หลังจากการสอบสวนเล็กน้อยฉันก็ได้ข้อสรุปที่น่าเศร้า ...

เห็นได้ชัดว่ามันเป็น js ภายในและคลุมเครือมากขึ้นโดยไม่มีตรรกะมากนัก ...

เพียงแค่พยายามที่

Array(4)==Array(4)

และไม่มีการบีบบังคับประเภทด้วย ...

Array(4)===Array(4)

และคุณจะได้รับ FALSE

คุณรู้ไหมว่าnull==null, null===nullและแม้กระทั่งการundefined==undefinedและundefined===undefinedผลตอบแทนจริง ... ดังนั้น ... มันเป็นบิตปิดบัง ...

Array(4)==[,,,] ควรจะเป็นจริงด้วย


ZEE, Array (4) == [,,,] จะไม่เป็นจริง ถ้าเราเปรียบเทียบวัตถุกับวัตถุดั้งเดิมวัตถุนั้นจะถูกแปลงเป็นดั้งเดิม นั่นคือเหตุผลที่เรียก toString ()
devsathish

อาร์เรย์ (x) ควรเป็นที่อยู่ของตัวสร้าง ... อย่างไรก็ตามในระบบ (อย่ากังวลว่าระบบประเภทใด) <identity_X> === <identity_X> ควรเป็นจริงเสมอ!
ZEE
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.