รหัสองค์ประกอบที่มีชื่อสามารถอ้างอิงเป็น JavaScript Globals PlatoBlockchain Data Intelligence ค้นหาแนวตั้ง AI.

รหัสองค์ประกอบที่มีชื่อสามารถอ้างอิงเป็น JavaScript Globals

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

หากนี่เป็นครั้งแรกที่คุณได้ยินเกี่ยวกับเรื่องนี้ เตรียมตัวให้พร้อม! เราสามารถเห็นมันในการดำเนินการได้ง่ายๆ โดยการเพิ่ม ID ให้กับองค์ประกอบใน HTML:

โดยปกติ เราจะกำหนดตัวแปรใหม่โดยใช้ querySelector("#cool") or getElementById("cool") เพื่อเลือกองค์ประกอบนั้น:

var el = querySelector("#cool");

แต่เรามีสิทธิ์เข้าถึง .แล้ว #cool โดยไม่มีพื้นฐานนั้น:

ดังนั้นใดๆ id - หรือ name แอตทริบิวต์สำหรับเรื่องนั้น - ใน HTML สามารถเข้าถึงได้ใน JavaScript โดยใช้ window[ELEMENT_ID]. อีกครั้ง นี่ไม่ใช่ "ใหม่" อย่างแน่นอน แต่เป็นเรื่องปกติที่จะเห็น

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

บริบทบางอย่าง

แนวทางนี้คือ ระบุไว้ในข้อกำหนด HTMLซึ่งอธิบายว่าเป็น “การเข้าถึงที่มีชื่อบน Window วัตถุ."

Internet Explorer เป็นคนแรกที่ใช้คุณลักษณะนี้ เบราว์เซอร์อื่น ๆ ทั้งหมดก็เพิ่มเช่นกัน ตุ๊กแกเป็นเบราว์เซอร์เพียงตัวเดียวในขณะนั้นที่ไม่สนับสนุนโดยตรงในโหมดมาตรฐาน โดยเลือกที่จะทำให้มันเป็นคุณลักษณะทดลองแทน มีความลังเลที่จะนำไปใช้เลย แต่ก็ ก้าวไปข้างหน้าในนามของความเข้ากันได้ของเบราว์เซอร์ (ตุ๊กแกก็พยายาม โน้มน้าว WebKit เพื่อย้ายออกจากโหมดมาตรฐาน) และในที่สุดก็เข้าสู่โหมดมาตรฐานใน Firefox 14

สิ่งหนึ่งที่อาจไม่เป็นที่ทราบกันดีนักคือเบราว์เซอร์ต้องมีมาตรการป้องกันไว้บ้าง — ด้วยระดับความสำเร็จที่แตกต่างกัน — เพื่อให้แน่ใจว่า globals ที่สร้างขึ้นจะไม่ทำให้หน้าเว็บเสียหาย หนึ่งในมาตรการดังกล่าวคือ...

เงาตัวแปร

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


  
    window.foo = "bar";
  


  
I won't override window.foo
console.log(window.foo); // Prints "bar"

และตรงกันข้ามก็เป็นจริงเช่นกัน:

I will be overridden :(
window.foo = "bar"; console.log(window.foo); // Prints "bar"

ลักษณะการทำงานนี้มีความสำคัญเนื่องจากจะลบล้างการแทนที่ที่เป็นอันตรายเช่น

ซึ่งมิฉะนั้นจะสร้างความขัดแย้งโดยการทำให้ .เป็นโมฆะ alert เอพีไอ เทคนิคการป้องกันนี้อาจเป็นเหตุผลที่คุณ — ถ้าคุณเป็นเหมือนฉัน — กำลังเรียนรู้เกี่ยวกับสิ่งนี้เป็นครั้งแรก

คดีที่มีชื่อ globals

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

  • หาก DOM เปลี่ยนแปลง ข้อมูลอ้างอิงก็เช่นกัน นั่นทำให้บางอย่าง "เปราะ" (ข้อกำหนดของข้อกำหนด สำหรับมัน) รหัสที่การแยกข้อกังวลระหว่าง HTML และ JavaScript อาจมากเกินไป
  • การอ้างอิงโดยบังเอิญนั้นง่ายเกินไป การพิมพ์ผิดอย่างง่ายอาจจบลงด้วยการอ้างอิงโกลบอลที่มีชื่อและให้ผลลัพธ์ที่ไม่คาดคิด
  • มีการใช้งานแตกต่างกันในเบราว์เซอร์ ตัวอย่างเช่น เราควรเข้าถึงสมอด้วย an id - เช่น — แต่เบราว์เซอร์บางตัว (เช่น Safari และ Firefox) ส่งคืน a ReferenceError ในคอนโซล
  • อาจไม่คืนสิ่งที่คุณคิด ตามข้อมูลจำเพาะ เมื่อมีหลายอินสแตนซ์ขององค์ประกอบที่มีชื่อเดียวกันใน DOM — พูด สองอินสแตนซ์ของ

    — เบราว์เซอร์ควรส่งคืน an HTMLCollection กับอาร์เรย์ของอินสแตนซ์ อย่างไรก็ตาม Firefox จะส่งคืนเฉพาะอินสแตนซ์แรกเท่านั้น แล้วอีกครั้ง สเปกบอกว่า เราควรใช้ตัวอย่างหนึ่งของ an id ในต้นไม้ขององค์ประกอบอยู่แล้ว แต่การทำเช่นนี้จะไม่ทำให้เพจทำงานหรืออะไรแบบนั้นได้

  • อาจมีค่าใช้จ่ายด้านประสิทธิภาพ? ฉันหมายความว่าเบราว์เซอร์ต้องทำรายการอ้างอิงและบำรุงรักษา สองสามคนทำการทดสอบ ในเธรด StackOverflow นี้โดยที่ชื่อ globals เป็นจริง มีประสิทธิภาพมากขึ้นในการทดสอบเดียว และ ประสิทธิภาพน้อยกว่าในการทดสอบล่าสุด.

ข้อควรพิจารณาเพิ่มเติม

สมมติว่าเราโยนคำวิพากษ์วิจารณ์ว่าใช้ globals ที่มีชื่อแล้วใช้ต่อไป มันเป็นเรื่องดีทั้งหมด. แต่มีบางสิ่งที่คุณอาจต้องการพิจารณาเมื่อคุณทำ

โพลีฟิล

การตรวจสอบสากลประเภทนี้เป็นข้อกำหนดในการตั้งค่าทั่วไปสำหรับโพลีฟิล ดูตัวอย่างต่อไปนี้ที่เราตั้งค่าคุกกี้โดยใช้ new CookieStore API, เติมลงในเบราว์เซอร์ที่ยังไม่รองรับ:


  
  
    // Polyfill the CookieStore API if not yet implemented.
    // https://developer.mozilla.org/en-US/docs/Web/API/CookieStore
    if (!window.cookieStore) {
      window.cookieStore = myCookieStorePolyfill;
    }
    cookieStore.set("foo", "bar");
  

รหัสนี้ใช้งานได้ดีใน Chrome แต่แสดงข้อผิดพลาดต่อไปนี้ใน Safari:

TypeError: cookieStore.set is not a function

Safari ขาดการสนับสนุนสำหรับ CookieStore API ณ วันที่เขียนนี้ จึงไม่มีการใช้โพลีฟิล เนื่องจาก img รหัสองค์ประกอบสร้างตัวแปรส่วนกลางที่ขัดแย้งกับ cookieStore ทั่วโลก

อัปเดต JavaScript API

เราสามารถพลิกสถานการณ์และพบปัญหาอื่นที่การอัปเดตกลไก JavaScript ของเบราว์เซอร์สามารถทำลายการอ้างอิงทั่วโลกขององค์ประกอบที่มีชื่อได้

ตัวอย่างเช่น:


  
  
    window.BarcodeDetector.focus();
  

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

คุณเห็นไหมว่าตัวแปรส่วนกลางที่เราใช้เพื่ออ้างอิงองค์ประกอบอินพุตจะหยุดทำงานทันทีที่เบราว์เซอร์เริ่มรองรับ BarcodeDetector API. ณ จุดนั้น window.BarcodeDetector global จะไม่อ้างอิงถึงองค์ประกอบอินพุตและ .อีกต่อไป .focus() จะขว้าง“window.BarcodeDetector.focus ไม่ใช่ข้อผิดพลาดของฟังก์ชัน

โบนัส: องค์ประกอบที่มีชื่อบางรายการเท่านั้นที่สร้างการอ้างอิงทั่วโลก

ต้องการที่จะได้ยินเรื่องตลก? เพื่อเพิ่มการดูถูกการบาดเจ็บ องค์ประกอบที่มีชื่อสามารถเข้าถึงได้เป็นตัวแปรส่วนกลางก็ต่อเมื่อชื่อนั้นไม่มีอะไรนอกจากตัวอักษร เบราว์เซอร์จะไม่สร้างการอ้างอิงทั่วโลกสำหรับองค์ประกอบที่มี ID ที่มีอักขระพิเศษและตัวเลข เช่น hello-world และ item1.

สรุป

สรุปว่าเรามาที่นี่ได้อย่างไร:

  • เบราว์เซอร์หลักทั้งหมดสร้างการอ้างอิงทั่วโลกไปยังแต่ละองค์ประกอบ DOM ด้วย an id (หรือในบางกรณี a name คุณลักษณะ).
  • การเข้าถึงองค์ประกอบเหล่านี้ผ่านการอ้างอิงทั่วโลกนั้นไม่น่าเชื่อถือและอาจเป็นอันตรายได้ ใช้ querySelector or getElementById แทน.
  • เนื่องจากการอ้างอิงทั่วโลกถูกสร้างขึ้นโดยอัตโนมัติ จึงอาจมีผลข้างเคียงบางอย่างกับโค้ดของคุณ นั่นเป็นเหตุผลที่ดีที่จะหลีกเลี่ยงการใช้ id คุณลักษณะเว้นแต่คุณต้องการจริงๆ

ท้ายที่สุด อาจเป็นความคิดที่ดีที่จะหลีกเลี่ยงการใช้ชื่อ globals ใน JavaScript ฉันอ้างอิงข้อมูลจำเพาะก่อนหน้านี้เกี่ยวกับวิธีการที่นำไปสู่รหัส "เปราะบาง" แต่นี่คือข้อความเต็มเพื่อขับเคลื่อนจุดกลับบ้าน:

ตามกฎทั่วไป การพึ่งพาสิ่งนี้จะทำให้โค้ดเปราะบาง รหัสใดที่เชื่อมโยงกับ API นี้สามารถเปลี่ยนแปลงได้เมื่อเวลาผ่านไป เนื่องจากมีการเพิ่มคุณสมบัติใหม่ลงในแพลตฟอร์มเว็บ เป็นต้น ให้ใช้ .แทน document.getElementById() or document.querySelector().

ฉันคิดว่าความจริงที่ว่าข้อมูลจำเพาะ HTML แนะนำให้อยู่ห่างจากคุณลักษณะนี้พูดสำหรับตัวเอง

ประทับเวลา:

เพิ่มเติมจาก เคล็ดลับ CSS