ฉันสังเกตเห็นในวันนี้ว่า Chrome 49 จะไม่แสดงผลอีกต่อไปNaN
เมื่อคุณพิมพ์{}+{}
ลงในคอนโซล [object Object][object Object]
แต่มันจะออกผลลัพธ์สตริง
ทำไมนี้ ภาษาเปลี่ยนไปหรือไม่?
ฉันสังเกตเห็นในวันนี้ว่า Chrome 49 จะไม่แสดงผลอีกต่อไปNaN
เมื่อคุณพิมพ์{}+{}
ลงในคอนโซล [object Object][object Object]
แต่มันจะออกผลลัพธ์สตริง
ทำไมนี้ ภาษาเปลี่ยนไปหรือไม่?
คำตอบ:
ตอนนี้ Chrome devtools จะห่อทุกอย่างที่ขึ้นต้นด้วย{
และลงท้ายด้วย}
วงเล็บโดยปริยายคู่ ( ดูรหัส ) เพื่อบังคับให้การประเมินผลเป็นนิพจน์ ด้วยวิธีนี้{}
สร้างวัตถุว่างเปล่าในขณะนี้ คุณสามารถดูนี้ถ้าคุณกลับไปถึงประวัติศาสตร์ ( ↑) (…)
บรรทัดก่อนหน้าจะถูกบรรจุอยู่ใน
ทำไม? ฉันไม่รู้ แต่ฉันเดาได้ว่ามันช่วยลดความสับสนสำหรับมือใหม่ที่ไม่รู้เรื่องของตัวบล็อกและวัตถุและมันก็มีประโยชน์มากขึ้นถ้าคุณต้องการประเมินการแสดงออก
และในความเป็นจริงนั่นคือเหตุผลที่กล่าวไว้ในข้อผิดพลาด 499864 สะดวกสบายอย่างแท้จริง และเนื่องจากโหนด REPL ก็มีเช่นกัน ( ดูรหัส )
{a:1}),({b:2}
ควรเกิดข้อผิดพลาดไม่ใช่สร้างวัตถุ
)
ในกรณีที่มันอยู่ในความคิดเห็นเช่น{a:3} // :-}
อาจยังคงผลิตวัตถุ
ถ้าคุณกดลูกศรขึ้นหลังจากการตรวจสอบนี้คุณจะสังเกตเห็นว่าแทน{} + {}
มันแสดงซึ่งผลในการ({} + {})
"[object Object][object Object]"
ในการเปรียบเทียบใน Firefox {} + {}
จะยังคงปรากฏNaN
แต่ถ้าคุณทำ({} + {})
มันก็จะปรากฏ"[object Object][object Object]"
ขึ้น
ดังนั้นดูเหมือนว่า Chrome จะเพิ่มวงเล็บล้อมรอบโดยอัตโนมัติเมื่อเห็นการดำเนินการนี้
{} + {}
เมื่อไม่ "ทำความสะอาด" ให้({} + {})
ถือว่าเป็น+ {}
เพราะ{}
ถูกแยกวิเคราะห์เป็นบล็อกว่างเปล่า
{}
นั้นเป็นเพียงแค่โค้ดบล็อกว่างเปล่าและไม่สนใจปล่อยให้เรา+{}
ซึ่งเป็น+
วัตถุที่ไม่มีค่าและว่างเปล่า การเริ่มต้น +
จะบีบบังคับอาร์กิวเมนต์ให้เป็นตัวเลขซึ่งเกี่ยวข้องกับการแปลงวัตถุให้เป็นแบบดั้งเดิม (ซึ่งจะจบลงด้วยการเป็นtoString
ในกรณีนี้ส่งผลให้"[object Object]"
) และดังนั้นเราจึงได้รับ+"[object Object]"
ซึ่งเป็นNaN
เพราะ"[object Object]"
ไม่สามารถแปลงเป็นจำนวนที่ถูกต้อง
น่าเสียดายที่ฉันเพิ่ม Clippy พูดด้วยตัวเอง คอนโซลไม่ให้ข้อมูลเกี่ยวกับสิ่งที่ทำเพื่อคุณ
กฎใหม่นั้นเรียบง่ายอย่างไม่น่าเชื่อช่วยให้เราสามารถพิมพ์ตัวอักษรสองตัวที่ยากลำบากเหล่านี้o=
หรือ0,
ก่อนที่จะวาง Object Objectals ลงในคอนโซล:
{
;{wat:1}),({wat:2}
ในที่สุดก็เป็นข้อผิดพลาดอีกครั้ง
{let i=0;var increment=_=>i++}
ได้รับอนุญาตอย่างถูกต้องในที่สุดซึ่งเป็นวิธีที่ดีในการทำปิด
อย่างไรก็ตามสิ่งต่อไปนี้เป็นวัตถุที่ไม่ถูกต้องนี่เป็นเพียงความสะดวกสบายตามที่ระบุไว้โดย @Bergi ซึ่งตีความ JS ผิดเพื่อช่วยคุณ! ข้อมูลจำเพาะบอกว่ามันเป็นบล็อกที่มีข้อความกำกับ "foo" ที่มีตัวอักษร 1 ที่ไม่ได้กำหนดให้กับอะไร
{foo:1}
ข้างต้นควรเป็นเช่นเดียวกับ
if(1) {
foo: 1
}
ต่อไปนี้จะถือว่าเป็นบล็อกอย่างถูกต้อง ... เนื่องจากมีความคิดเห็นอยู่ข้างหน้า!
//magic comment
{foo:1}
ดังนั้นนี่คือ:
{foo:1}
//also magic
นี่คือวัตถุ:
{foo:
//not so magic comment
1}
นี่เป็นข้อผิดพลาด
//not so magic comment
{foo:1}.foo
ดังนั้นนี่คือ:
{foo:1}.foo
นี่เป็นเรื่องปกติ:
1..wat
undefined
ดังนั้นนี่คือ:
['foo'][0]
สิ่งต่อไปนี้ถูกตีความอย่างถูกต้องว่าเป็นวัตถุที่ตีเข้าไปในตำแหน่งนิพจน์0,
ซึ่งโดยทั่วไปแล้วเรามั่นใจได้อย่างชัดเจนว่าเรามีการแสดงออกแทนที่จะเป็นคำสั่ง
0,{foo:1}.foo
ฉันไม่เข้าใจว่าทำไมพวกเขาถึงห่อค่าในการล้อ JS มีการตัดสินใจการออกแบบที่ไร้สาระ แต่การพยายามทำให้มันดีกว่าในสถานการณ์นี้ไม่ใช่ตัวเลือกจริงๆคอนโซลจำเป็นต้องรัน JS อย่างถูกต้องและเราต้องมั่นใจว่า Chrome ไม่ได้คาดเดาว่าเราคิดว่าเราคิด จริงๆหมายถึงมันจะทำอย่างอื่น
หากคุณไม่ชอบเครื่องหมายจุลภาคคุณสามารถใช้การมอบหมาย
x = {foo:1}.foo
เพราะอย่างที่มันยืน
{} + {} + {}
"[object Object][object Object][object Object]"
;{} + {} + {}
"NaN[object Object]"
บ้าและสอดคล้องฉันสามารถจัดการกับ ... บ้าและไม่สอดคล้องไม่ขอบคุณ!
{foo:1}
และ{foo:1}//
ผลิตสิ่งเดียวกัน ใน Chrome JS REPL พวกเขาทำไม่ได้ REPL กำลังทำมากกว่าการประเมิน JS มันกำลังประมวลผลสตริงและตัดสินใจไปยังสิ่งต่าง ๆ
var x = eval('{a:1}')
ใน JavaScript x ที่ถูกต้องคือตอนนี้ 1 ไม่ใช่วัตถุที่ใช้งานง่ายกว่า {a: 1} ใช่มันแปลก แต่คุณไม่สามารถเปลี่ยนภาษาได้เพราะมันทำสิ่งแปลก ๆ ทุกอย่างนอกเหนือจากสตริง JSON จะถูกตีความเป็น JavaScript และประเมินผล การพิมพ์0,
ก่อนวาง JSON นั้นไม่ใช่เรื่องยากอีกทางหนึ่งฉันยินดีที่จะเตือนว่าสตริงถูกตีความว่าเป็นวัตถุแทนที่จะเป็น JavaScript เพื่อความสะดวก
var e = {}; e.toString()
แล้วคุณจะเห็นว่าฉันหมายถึงอะไร