คำถามที่พบบ่อยเกี่ยวกับ SmooshGate

น้ำหอมเกิดจากอะไร

ดูเหมือนว่าข้อเสนอสำหรับฟีเจอร์ภาษา JavaScript ที่ชื่อ Array.prototype.flatten จะใช้ร่วมกับเว็บไม่ได้ การจัดส่งฟีเจอร์นี้ใน Firefox Nightly ทำให้เว็บไซต์ยอดนิยมอย่างน้อย 1 เว็บไซต์ใช้งานไม่ได้ เนื่องจากโค้ดที่เป็นปัญหาเป็นส่วนหนึ่งของไลบรารี MooTools ที่แพร่หลาย จึงมีแนวโน้มที่เว็บไซต์จำนวนมากจะได้รับผลกระทบ (แม้ว่า MooTools จะไม่ได้มีการใช้งานกันอย่างแพร่หลายในเว็บไซต์ใหม่ๆ ในปี 2018 แต่ก็เคยได้รับความนิยมมากและยังคงอยู่ในเว็บไซต์ที่ใช้งานจริงหลายแห่ง)

ผู้เขียนข้อเสนอพูดติดตลกให้เปลี่ยนชื่อ flatten เป็น smoosh เพื่อหลีกเลี่ยงปัญหาความเข้ากันได้ มุกตลกไม่ชัดเจนสำหรับบางคน บางคนเริ่มเชื่ออย่างไม่ถูกต้องว่าชื่อใหม่ถูกตัดสินใจไปแล้ว และเหตุการณ์ต่างๆ ก็ได้ส่งต่ออย่างรวดเร็ว

Array.prototype.flatten มีหน้าที่อะไร

Array.prototype.flat ซึ่งเดิมเสนอเป็น Array.prototype.flatten จะแฟล็กอาร์เรย์แบบวนรอบจนถึง depth ที่ระบุ ซึ่งมีค่าเริ่มต้นเป็น 1

// Flatten one level:
const array = [1, [2, [3]]];
array.flat();
// → [1, 2, [3]]

// Flatten recursively until the array contains no more nested arrays:
array.flat(Infinity);
// → [1, 2, 3]

ข้อเสนอเดียวกันมี Array.prototype.flatMap ซึ่งเหมือนกับ Array.prototype.map เพียงแต่รวมผลลัพธ์ไว้ในอาร์เรย์ใหม่

[2, 3, 4].flatMap((x) => [x, x * 2]);
// → [2, 4, 3, 6, 4, 8]

MooTools ดำเนินการอะไรที่ทำให้เกิดปัญหานี้

MooTools กำหนด Array.prototype.flatten เวอร์ชันที่ไม่เป็นไปตามมาตรฐานของตนเอง ดังนี้

Array.prototype.flatten = /* non-standard implementation */;

การใช้งาน flatten ของ MooTools แตกต่างจากมาตรฐานที่เสนอ แต่นี่ไม่ใช่ปัญหา เมื่อจัดส่งเบราว์เซอร์ Array.prototype.flatten แบบเนทีฟ MooTools จะลบล้างการใช้งานแบบเนทีฟ วิธีนี้ช่วยให้โค้ดที่ต้องอาศัยลักษณะการทำงานของ MooTools ทำงานได้ตามที่ต้องการ ไม่ว่าโฆษณาเนทีฟจะมี flatten หรือไม่ก็ตาม ไปได้สวย!

ขออภัย มีบางอย่างเกิดขึ้น MooTools จะคัดลอกเมธอดอาร์เรย์ที่กำหนดเองทั้งหมดไปยัง Elements.prototype (โดยที่ Elements คือ API สำหรับ MooTools)

for (var key in Array.prototype) {
  Elements.prototype[key] = Array.prototype[key];
}

for-in จะทำซ้ำผ่านพร็อพเพอร์ตี้ที่ "แจกแจงได้" ซึ่งไม่ได้รวมวิธีการแบบเนทีฟ เช่น Array.prototype.sort แต่รวมพร็อพเพอร์ตี้ที่กำหนดเป็นประจำ เช่น Array.prototype.foo = whatever อย่างไรก็ตาม หากคุณเขียนทับพร็อพเพอร์ตี้ที่แจกแจงไม่ได้ เช่น Array.prototype.sort = whatever ค่านั้นจะยังคงไม่สามารถแจกแจงได้

ปัจจุบัน Array.prototype.flatten = mooToolsFlattenImplementation สร้างพร็อพเพอร์ตี้ flatten ที่ขยายได้ ดังนั้นระบบจะคัดลอกพร็อพเพอร์ตี้ดังกล่าวไปยัง Elements ในภายหลัง แต่หากเบราว์เซอร์ส่ง flatten เวอร์ชันเดิมมา เบราว์เซอร์จะแจกแจงไม่ได้และไม่คัดลอกไปยัง Elements ตอนนี้โค้ดที่อาศัย Elements.prototype.flatten ของ MooTools ไม่สมบูรณ์

แม้ว่าดูเหมือนว่าการเปลี่ยน Array.prototype.flatten เนทีฟให้เป็นแบบแจกแจงได้จะช่วยแก้ปัญหาได้ แต่ก็น่าจะทำให้เกิดปัญหาเกี่ยวกับความเข้ากันได้มากขึ้น ทุกเว็บไซต์ที่ใช้ for-in ทำซ้ำในอาร์เรย์ (ซึ่งเป็นแนวทางปฏิบัติที่ไม่ดีแต่ก็เกิดขึ้นได้) จากนั้นจะมีการดำเนินการวนซ้ำเพิ่มเติมโดยกะทันหันสำหรับพร็อพเพอร์ตี้ flatten

ปัญหาพื้นฐานที่ใหญ่กว่านี้คือการแก้ไขออบเจ็กต์ในตัว ปัจจุบันการขยายต้นแบบเนทีฟถือเป็นแนวทางปฏิบัติที่ไม่ดี เนื่องจากไม่ได้เขียนร่วมกับไลบรารีอื่นๆ และโค้ดของบุคคลที่สามได้อย่างสวยงาม อย่าแก้ไขออบเจ็กต์ที่คุณไม่ได้เป็นเจ้าของ

ทำไมเราไม่เก็บชื่อที่ใช้ในปัจจุบันไว้และทำลายเว็บไปเลยล่ะ

ในปี 1996 ก่อนที่ CSS จะแพร่หลาย และนานมาแล้วก่อนที่ “HTML5” จะกลายเป็นสิ่งที่เว็บไซต์ Space Jam เผยแพร่ ปัจจุบันเว็บไซต์ยังคงทำงาน เหมือนเมื่อ 22 ปีที่แล้ว

มันเกิดขึ้นได้อย่างไร มีคนดูแลเว็บไซต์นั้นมาตลอดหลายปีไหม โดยอัปเดต ทุกครั้งที่ผู้ให้บริการเบราว์เซอร์จัดส่งฟีเจอร์ใหม่

ผลที่ได้คือ "อย่าทำลายเว็บ" เป็นหลักการออกแบบอันดับหนึ่ง สำหรับ HTML, CSS, JavaScript และมาตรฐานอื่นๆ ที่ใช้กันอย่างแพร่หลายบนเว็บ หากการจัดส่งฟีเจอร์เบราว์เซอร์ใหม่จะทำให้เว็บไซต์ที่มีอยู่หยุดทำงาน นั่นเป็นผลเสียต่อทุกคน เช่น

  • ผู้เข้าชมเว็บไซต์ที่ได้รับผลกระทบได้รับประสบการณ์การใช้งานที่ไม่ดีอย่างกะทันหัน
  • เจ้าของเว็บไซต์เปลี่ยนจากการมีเว็บไซต์ที่ใช้งานได้ดีเยี่ยม ไปเป็นเว็บไซต์ที่ใช้งานไม่ได้โดยไม่มีการเปลี่ยนแปลงใดๆ
  • ผู้ให้บริการเบราว์เซอร์ที่ส่งคุณลักษณะใหม่นี้สูญเสียส่วนแบ่งการตลาดเนื่องจากผู้ใช้เปลี่ยนเบราว์เซอร์หลังจากที่สังเกตเห็นว่า "ทำงานได้ในเบราว์เซอร์ X"
  • เมื่อทราบปัญหาด้านความเข้ากันได้ ผู้ให้บริการเบราว์เซอร์รายอื่นจะปฏิเสธการจัดส่ง ข้อกำหนดของฟีเจอร์ไม่ตรงกับความเป็นจริง ("ไม่มีอะไรนอกจากเป็นนิยาย") ซึ่งส่งผลเสียต่อกระบวนการกำหนดมาตรฐาน

แน่นอนว่า MooTools ที่ผ่านมาได้ทำสิ่งที่ผิด แต่การทำลายเว็บ ไม่ได้ลงโทษผู้ใช้ แต่เป็นการลงโทษผู้ใช้ ผู้ใช้เหล่านี้ไม่ทราบว่าเครื่องมือ Moo คืออะไร หรือเราสามารถหาวิธีอื่น และผู้ใช้สามารถใช้เว็บต่อไปได้ ตัวเลือกนี้ทำได้ง่ายๆ

นั่นหมายความว่าจะนำ API ที่ไม่ดีออกจากแพลตฟอร์มเว็บไม่ได้ใช่ไหม

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

<applet>, <keygen> และ showModalDialog() เป็นตัวอย่าง API ที่ไม่ดีซึ่งนำออกจากแพลตฟอร์มเว็บได้สำเร็จ

เหตุใดเราจึงไม่แก้ไขแค่ MooTools

การแพตช์ MooTools เพื่อไม่ให้ขยายออบเจ็กต์ในตัวอีกต่อไปถือเป็นความคิดที่ดี แต่วิธีนี้ไม่ได้แก้ไขปัญหาเฉพาะหน้า ถึงแม้ว่า MooTools จะเปิดตัวเวอร์ชันที่เป็นแพตช์ แต่เว็บไซต์ที่มีอยู่ทั้งหมดที่ใช้เวอร์ชันนี้จะต้องอัปเดตเพื่อไม่ให้ปัญหาเรื่องความเข้ากันได้หายไป

ผู้ใช้จะอัปเดตสำเนาของ MooTools ไม่ได้ใช่ไหม

ในโลกที่สมบูรณ์แบบ MooTools เปิดตัวแพตช์ และทุกๆ เว็บไซต์ที่ใช้ MooTools จะอัปเดตได้อย่างน่าอัศจรรย์ในวันถัดไป ปัญหาได้รับการแก้ไขแล้ว ใช่ไหม!

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

โปรดทราบว่าเว็บไซต์เหล่านี้หลายเว็บเก่าแล้วและอาจไม่ได้รับการดูแลรักษา แม้ว่าผู้ดูแลเว็บไซต์จะยังอยู่ แต่เป็นไปได้ว่าพวกเขาไม่ใช่นักพัฒนาเว็บที่มีทักษะสูงเหมือนคุณ เราไม่อาจคาดหวังได้ว่าทุกคนจะไปเปลี่ยนเว็บไซต์ ที่มีอายุ 8 ขวบของตนเนื่องจากปัญหาความเข้ากันได้ของเว็บ

กระบวนการของ TC39 ทำงานอย่างไร

TC39 เป็นคณะกรรมการที่รับผิดชอบการพัฒนาภาษา JavaScript ผ่านมาตรฐาน ECMAScript

#SmooshGate ทำให้บางคนเชื่อว่า "TC39 ต้องการเปลี่ยนชื่อ flatten เป็น smoosh" แต่นี่เป็นเรื่องตลกที่ไม่ค่อยสื่อสารกับภายนอก การตัดสินใจสำคัญๆ เช่น การเปลี่ยนชื่อข้อเสนอ อย่างรอบคอบ ไม่ได้เกิดขึ้นโดยคนคนเดียว และไม่ใช้เวลาชั่วข้ามคืนโดยยึดตามความคิดเห็นของ GitHub เดียว

TC39 มีกระบวนการทดลองใช้ที่ชัดเจนสำหรับข้อเสนอฟีเจอร์ ข้อเสนอ ECMAScript และการเปลี่ยนแปลงสำคัญใดๆ ที่มีต่อข้อเสนอ (รวมถึงการเปลี่ยนชื่อวิธีการ) มีการหารือระหว่างการประชุม TC39 และจะต้องได้รับการอนุมัติจากคณะกรรมการทั้ง 2 ฝ่ายก่อนจึงจะได้เป็นทางการ ในกรณีของ Array.prototype.flatten ข้อเสนอได้ดำเนินการตามข้อตกลงหลายขั้นตอนแล้ว ไปจนถึงขั้นที่ 3 ซึ่งแสดงให้เห็นว่าฟีเจอร์ดังกล่าวพร้อมที่จะนำไปใช้ในเว็บเบราว์เซอร์แล้ว โดยปกติปัญหาเกี่ยวกับข้อกำหนดเพิ่มเติมจะเกิดขึ้นระหว่างการใช้งาน ในกรณีนี้ ความคิดเห็นที่สำคัญที่สุดหลังจากพยายามจัดส่ง นั่นคือฟีเจอร์ในสถานะปัจจุบัน ทำให้เว็บเสียหาย ปัญหาที่คาดเดาได้ยากเช่นนี้เป็นเหตุผลหนึ่งที่ทำให้กระบวนการของ TC39 ไม่จบลงเมื่อเบราว์เซอร์มีฟีเจอร์หนึ่งให้ใช้งาน

TC39 ดำเนินงานโดยฉันทามติ ซึ่งหมายความว่าคณะกรรมการต้องยอมรับการเปลี่ยนแปลงใหม่ๆ แม้ว่า smoosh จะเป็นคำแนะนำที่จริงจัง แต่ดูเหมือนว่าสมาชิกคณะกรรมการอาจไม่เห็นด้วยกับการใช้ชื่อที่ใช้ทั่วไปมากกว่า เช่น compact หรือ chain

การเปลี่ยนชื่อจาก flatten เป็น smoosh (แม้ว่าจะไม่ใช่เรื่องตลกก็ตาม) ในการประชุม TC39 ยังไม่มีการพูดคุยถึงกัน ดังนั้น จุดยืนอย่างเป็นทางการของ TC39 เกี่ยวกับหัวข้อนี้ยังไม่เป็นที่รู้จัก จะไม่มีใครพูดในนามของ TC39 ทุกคนได้เลยจนกว่าจะมีฉันทามติในการประชุมครั้งต่อไป

การประชุม TC39 มักเป็นการประชุมของกลุ่มคนที่มีภูมิหลังหลากหลาย บางคนมีประสบการณ์ออกแบบภาษาโปรแกรมมาหลายปี บางคนทำงานบนเบราว์เซอร์หรือเครื่องมือ JavaScript และมีผู้เข้าร่วมเป็นตัวแทนชุมชนนักพัฒนาซอฟต์แวร์ JavaScript จำนวนมาก

ในที่สุดแล้ว SmooshGate แก้ปัญหาได้อย่างไร

ในระหว่างการประชุม TC39 เดือนพฤษภาคม 2018 #SmooshGate ได้รับการแก้ไขอย่างเป็นทางการแล้วด้วยการเปลี่ยนชื่อ flatten เป็น flat

Array.prototype.flat และ Array.prototype.flatMap จัดส่งใน V8 v6.9 และ Chrome 69