เหตุใด {} + {} จึงไม่มี NaN ในคอนโซล Chrome อีกต่อไป


144

ฉันสังเกตเห็นในวันนี้ว่า Chrome 49 จะไม่แสดงผลอีกต่อไปNaNเมื่อคุณพิมพ์{}+{}ลงในคอนโซล [object Object][object Object]แต่มันจะออกผลลัพธ์สตริง

ทำไมนี้ ภาษาเปลี่ยนไปหรือไม่?


13
ดูเหมือนว่าตอนนี้ Chrome จะถือว่าการดำเนินการนี้เป็นสตริงที่ต่อกันมากกว่าการเพิ่ม ทำไมถึงเป็นฉันไม่รู้ซึ่งเป็นเหตุผลว่าทำไมนี่คือความคิดเห็นไม่ใช่คำตอบ :) ลองvar e = {}; e.toString()แล้วคุณจะเห็นว่าฉันหมายถึงอะไร
user428517

19
"ภาษาเปลี่ยนไปหรือไม่" ไม่
เฟลิกซ์ลิ่ง

6
@FelixKling จะเปลี่ยนแปลงภาษา? ... ไม่มี : c
cat

18
บางทีWATMANมีบางอย่างเกี่ยวข้องกับมันหรือไม่?
rickster

1
@ เคล็ดลับนั่นคือวิธีที่ฉันได้พบมัน ฉันสร้างมันขึ้นมาใหม่เพื่อการนำเสนอ
Filip Haglund

คำตอบ:


152

ตอนนี้ Chrome devtools จะห่อทุกอย่างที่ขึ้นต้นด้วย{และลงท้ายด้วย}วงเล็บโดยปริยายคู่ ( ดูรหัส ) เพื่อบังคับให้การประเมินผลเป็นนิพจน์ ด้วยวิธีนี้{}สร้างวัตถุว่างเปล่าในขณะนี้ คุณสามารถดูนี้ถ้าคุณกลับไปถึงประวัติศาสตร์ ( ) (…)บรรทัดก่อนหน้าจะถูกบรรจุอยู่ใน

ทำไม? ฉันไม่รู้ แต่ฉันเดาได้ว่ามันช่วยลดความสับสนสำหรับมือใหม่ที่ไม่รู้เรื่องของตัวบล็อกและวัตถุและมันก็มีประโยชน์มากขึ้นถ้าคุณต้องการประเมินการแสดงออก

และในความเป็นจริงนั่นคือเหตุผลที่กล่าวไว้ในข้อผิดพลาด 499864 สะดวกสบายอย่างแท้จริง และเนื่องจากโหนด REPL ก็มีเช่นกัน ( ดูรหัส )


182
Stupid Chrome {a:1}),({b:2}ควรเกิดข้อผิดพลาดไม่ใช่สร้างวัตถุ
Oriol

29
นั่นคือสิ่งที่จะเกิดขึ้นเมื่อคุณแยกวิเคราะห์โครงสร้างที่ซ้อนกันโดยพลการด้วย regex stackoverflow.com/questions/1732348/ …
Filip Haglund

4
ฉันไม่มีความคิดว่าทำไม แต่อย่างใดเมื่อฉันเห็นข้อความของฉันที่นั่นฉันรู้สึก "มีชื่อเสียง" แม้ว่าหน้านั้นจะเป็นสาธารณะเช่นเดียวกับที่นี้: D ปัญหาแปลก StackOverflow ต่อไปนี้เป็นคำตอบที่เก่ากว่าของฉันเกี่ยวกับปัญหาstackoverflow.com/questions/17268468/…
Benjamin Gruenbaum

3
ฉันไม่ชอบการนำไปใช้ในปัจจุบันและวางแผนที่จะแก้ไข bugs.chromium.org/p/chromium/issues/detail?id=499864#c17
Zirak

1
@Zirak โชคดีที่ได้รับการแก้ไขขยะ, IMO มันควรได้รับการสนับสนุนโดยเร็วที่สุด แต่ถ้าคุณต้องการปรับปรุงให้พิจารณาเพิ่มบรรทัดใหม่ก่อนที่จะแทรก)ในกรณีที่มันอยู่ในความคิดเห็นเช่น{a:3} // :-}อาจยังคงผลิตวัตถุ
Oriol

44

ถ้าคุณกดลูกศรขึ้นหลังจากการตรวจสอบนี้คุณจะสังเกตเห็นว่าแทน{} + {}มันแสดงซึ่งผลในการ({} + {})"[object Object][object Object]"

ในการเปรียบเทียบใน Firefox {} + {}จะยังคงปรากฏNaNแต่ถ้าคุณทำ({} + {})มันก็จะปรากฏ"[object Object][object Object]"ขึ้น

ดังนั้นดูเหมือนว่า Chrome จะเพิ่มวงเล็บล้อมรอบโดยอัตโนมัติเมื่อเห็นการดำเนินการนี้


22
คำตอบนี้ถูกต้อง แต่ว้าวคนฉันไม่แน่ใจว่าฉันชอบโครเมี่ยมที่ทำอย่างนั้น google ไม่ดี
user428517

1
@ sgroves ฉันสนใจที่จะดูว่านี่เป็นสิ่งเดียวกันใน Canary หรือไม่และถ้ามันทำโดยมีจุดประสงค์หรือเป็นข้อบกพร่องจริงๆ
J. Titus

8
{} + {}เมื่อไม่ "ทำความสะอาด" ให้({} + {})ถือว่าเป็น+ {}เพราะ{}ถูกแยกวิเคราะห์เป็นบล็อกว่างเปล่า
Gregory Nisbet

7
ทำไมมันกลับมาตอนแรก?
0x499602D2

25
@ 0x499602D2: เพราะถ้าคุณไม่ทำ parens (หรือเป็นสาเหตุให้ parser เปลี่ยนเป็นนิพจน์แทนที่จะเป็นคำสั่ง) การเริ่มต้น{}นั้นเป็นเพียงแค่โค้ดบล็อกว่างเปล่าและไม่สนใจปล่อยให้เรา+{}ซึ่งเป็น+วัตถุที่ไม่มีค่าและว่างเปล่า การเริ่มต้น +จะบีบบังคับอาร์กิวเมนต์ให้เป็นตัวเลขซึ่งเกี่ยวข้องกับการแปลงวัตถุให้เป็นแบบดั้งเดิม (ซึ่งจะจบลงด้วยการเป็นtoStringในกรณีนี้ส่งผลให้"[object Object]") และดังนั้นเราจึงได้รับ+"[object Object]"ซึ่งเป็นNaNเพราะ"[object Object]"ไม่สามารถแปลงเป็นจำนวนที่ถูกต้อง
TJ Crowder

4

ตั้งแต่ Chrome 54 เกี่ยวกับคอนโซล:

📎- "ฉันแปลงบล็อกนั้นเป็นวัตถุสำหรับคุณ" -Clippy น่าเสียดายที่ฉันเพิ่ม Clippy พูดด้วยตัวเอง คอนโซลไม่ให้ข้อมูลเกี่ยวกับสิ่งที่ทำเพื่อคุณ

กฎใหม่นั้นเรียบง่ายอย่างไม่น่าเชื่อช่วยให้เราสามารถพิมพ์ตัวอักษรสองตัวที่ยากลำบากเหล่านี้o=หรือ0,ก่อนที่จะวาง Object Objectals ลงในคอนโซล:

  • หากคุณมีรหัสที่ขึ้นต้นด้วย: ช่องว่างเสริม (ไม่อนุญาตให้แสดงความคิดเห็น) ตามด้วย{;
  • และรหัสนั้นสามารถตีความได้ว่าเป็นวัตถุ
  • และวัตถุนั้นตามมาด้วยรหัสอื่นไม่มีเว้นแต่:
  • รหัสหลังจากวัตถุแรกคือตัวดำเนินการแบบไบนารี
  • จากนั้นสามารถดำเนินการได้มากเท่าที่คุณต้องการรวมถึงการจัดกลุ่ม
  • หากผู้ปฏิบัติงานคนสุดท้ายมี Object ตามตัวอักษรอยู่ในตำแหน่งมือขวา
  • และวัตถุสุดท้ายนั้นไม่ได้ถูกจัดกลุ่มเป็น parens
  • และรหัสนั้นไม่ได้ถูกยกเลิกด้วยเครื่องหมายอัฒภาค
  • และไม่มีความคิดเห็นตามรหัส (อนุญาตให้แสดงความคิดเห็นภายในตราบเท่าที่พวกเขาไม่ได้อยู่ในตำแหน่งเริ่มต้นหรือตำแหน่งสุดท้าย)
  • จากนั้น JavaScript ของคุณเท่านั้น (ซึ่งอาจจริงหรืออาจไม่ใช่รหัสที่ถูกต้อง) จะถูก intrepted ใหม่เป็นวัตถุที่ถูกต้อง คุณจะไม่ได้รับแจ้งว่ารหัสของคุณถูกตีความใหม่

{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]"

บ้าและสอดคล้องฉันสามารถจัดการกับ ... บ้าและไม่สอดคล้องไม่ขอบคุณ!


REPL ไม่ใช่ภาษาที่เป็น REPL มันผ่านสตริงภาษาเหนือสิ่งอื่นใด นี่คือสิ่งที่หลาย Chrome REPL ไม่ภาษาตัวเองไม่ได้ มันค่อนข้างมีประโยชน์ดังนั้นฉันดีใจที่พวกเขาไม่ได้ใช้ภาษาธรรมดา
gman

@gman A REPL อ่านสตริงประเมินผลพิมพ์ผลลัพธ์แล้วเตรียมที่จะอ่านโค้ดไดนามิกชิ้นถัดไป ไม่มีสิ่งใดในหน้าเชื่อมโยงที่เป็น JavaScript ที่ไม่ถูกต้อง ตัวแปร "$ _" ที่ถูกกำหนดขอบเขตให้กับบริบทคอนโซลนั้นเป็นความสะดวกสบายที่ชัดเจนใน REPL เท่านั้น อย่างไรก็ตาม "$ _" เป็นชื่อตัวแปรที่ถูกต้องส่วนที่เหลือเป็นเพียงฟังก์ชั่นปกติและคลาสที่เรียกใช้ด้วย JavaScript ปกติ
James Wakefield

ไม่แน่ใจว่าประเด็นของคุณคืออะไร ประเด็นของฉันคือภาษาเป็นสิ่งหนึ่งสภาพแวดล้อมที่ใช้เป็นอีกสิ่งหนึ่ง คุณยกตัวอย่างในคำตอบของคุณ ใน JS {foo:1}และ{foo:1}//ผลิตสิ่งเดียวกัน ใน Chrome JS REPL พวกเขาทำไม่ได้ REPL กำลังทำมากกว่าการประเมิน JS มันกำลังประมวลผลสตริงและตัดสินใจไปยังสิ่งต่าง ๆ
gman

var x = eval('{a:1}')ใน JavaScript x ที่ถูกต้องคือตอนนี้ 1 ไม่ใช่วัตถุที่ใช้งานง่ายกว่า {a: 1} ใช่มันแปลก แต่คุณไม่สามารถเปลี่ยนภาษาได้เพราะมันทำสิ่งแปลก ๆ ทุกอย่างนอกเหนือจากสตริง JSON จะถูกตีความเป็น JavaScript และประเมินผล การพิมพ์0,ก่อนวาง JSON นั้นไม่ใช่เรื่องยากอีกทางหนึ่งฉันยินดีที่จะเตือนว่าสตริงถูกตีความว่าเป็นวัตถุแทนที่จะเป็น JavaScript เพื่อความสะดวก
James Wakefield
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.