ID Elemen Bernama Dapat Direferensikan sebagai JavaScript Globals PlatoBlockchain Data Intelligence. Pencarian Vertikal. Ai.

ID Elemen Bernama Dapat Direferensikan sebagai JavaScript Globals

Tahukah Anda bahwa elemen DOM dengan ID dapat diakses di JavaScript sebagai variabel global? Itu salah satu hal yang sudah ada, seperti, selamanya tapi saya benar-benar menggalinya untuk pertama kalinya.

Jika ini pertama kalinya Anda mendengarnya, bersiaplah! Kita dapat melihatnya beraksi hanya dengan menambahkan ID ke elemen dalam HTML:

Biasanya, kami akan mendefinisikan variabel baru menggunakan querySelector("#cool") or getElementById("cool") untuk memilih elemen itu:

var el = querySelector("#cool");

Tapi kami sebenarnya sudah memiliki akses ke #cool tanpa omong kosong itu:

Jadi, apa saja id - atau name atribut, dalam hal ini โ€” dalam HTML dapat diakses dalam JavaScript menggunakan window[ELEMENT_ID]. Sekali lagi, ini tidak benar-benar "baru" tetapi sangat jarang untuk dilihat.

Seperti yang Anda duga, mengakses lingkup global dengan referensi bernama bukanlah ide terbaik. Beberapa orang datang untuk menyebut ini "pencemar lingkup global." Kami akan membahas mengapa demikian, tetapi pertama-tama ...

Beberapa konteks

Pendekatan ini diuraikan dalam spesifikasi HTML, yang digambarkan sebagai โ€œakses bernama pada Window obyek."

Internet Explorer adalah yang pertama mengimplementasikan fitur tersebut. Semua browser lain juga menambahkannya. Gecko adalah satu-satunya browser pada saat itu yang tidak mendukungnya secara langsung dalam mode standar, dan memilih untuk menjadikannya sebagai fitur eksperimental. Ada keraguan untuk menerapkannya sama sekali, tapi itu bergerak maju atas nama kompatibilitas browser (Tokek bahkan mencoba untuk meyakinkan WebKit untuk memindahkannya dari mode standar) dan akhirnya berhasil masuk ke mode standar di Firefox 14.

Satu hal yang mungkin tidak diketahui dengan baik adalah bahwa browser harus menerapkan beberapa tindakan pencegahan โ€” dengan berbagai tingkat keberhasilan โ€” untuk memastikan global yang dihasilkan tidak merusak halaman web. Salah satu tindakan tersebut adalahโ€ฆ

Bayangan variabel

Mungkin bagian yang paling menarik dari fitur ini adalah referensi elemen bernama tidak bayangan variabel global yang ada. Jadi, jika elemen DOM memiliki id yang sudah didefinisikan sebagai global, itu tidak akan menimpa yang sudah ada. Sebagai contoh:


  
    window.foo = "bar";
  


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

Dan kebalikannya juga benar:

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

Perilaku ini penting karena meniadakan penggantian berbahaya seperti

, yang sebaliknya akan menimbulkan konflik dengan membatalkan alert API. Teknik pengamanan ini mungkin menjadi alasan mengapa Anda โ€” jika Anda seperti saya โ€” mempelajari hal ini untuk pertama kalinya.

Kasus melawan global bernama

Sebelumnya, saya mengatakan bahwa menggunakan elemen bernama global sebagai referensi mungkin bukan ide terbaik. Ada banyak alasan untuk itu, yang TJ VanToll telah meliput dengan baik di blognya dan saya rangkum disini :

  • Jika DOM berubah, maka referensi juga akan berubah. Itu membuat beberapa orang benar-benar "rapuh" (istilah spesifikasi untuk itu) kode di mana pemisahan masalah antara HTML dan JavaScript mungkin terlalu banyak.
  • Referensi yang tidak disengaja terlalu mudah. Kesalahan ketik sederhana mungkin berakhir dengan referensi global bernama dan memberi Anda hasil yang tidak terduga.
  • Ini diterapkan secara berbeda di browser. Misalnya, kita harus dapat mengakses jangkar dengan id - mis โ€” tetapi beberapa browser (yaitu Safari dan Firefox) kembali ReferenceError di konsol.
  • Itu mungkin tidak mengembalikan apa yang Anda pikirkan. Menurut spesifikasi, ketika ada beberapa instance dari elemen bernama yang sama di DOM โ€” katakanlah, dua instance dari

    โ€” browser harus kembali dan HTMLCollection dengan array instance. Firefox, bagaimanapun, hanya mengembalikan contoh pertama. Kemudian lagi, spesifikasi mengatakan kita harus menggunakan satu contoh dari id di pohon elemen pula. Tetapi melakukan hal itu tidak akan menghentikan halaman agar tidak berfungsi atau semacamnya.

  • Mungkin ada biaya kinerja? Maksud saya, browser harus membuat daftar referensi itu dan memeliharanya. Beberapa orang menjalankan tes di utas StackOverflow ini, di mana nama global sebenarnya lebih berkinerja dalam satu tes dan kurang berkinerja dalam tes yang lebih baru.

Pertimbangan tambahan

Katakanlah kita membuang kritik terhadap penggunaan global bernama dan tetap menggunakannya. Semuanya baik. Tetapi ada beberapa hal yang mungkin ingin Anda pertimbangkan saat melakukannya.

Polyfill

Kedengarannya seperti edge-case-y, jenis pemeriksaan global ini adalah persyaratan penyiapan umum untuk polyfill. Lihat contoh berikut di mana kami mengatur cookie menggunakan yang baru CookieStore API, polyfilling di browser yang belum mendukungnya:


  
  
    // 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");
  

Kode ini berfungsi dengan baik di Chrome, tetapi memunculkan kesalahan berikut di Safari.:

TypeError: cookieStore.set is not a function

Safari tidak memiliki dukungan untuk CookieStore API pada tulisan ini. Akibatnya, polyfill tidak diterapkan karena img ID elemen membuat variabel global yang bentrok dengan cookieStore global

Pembaruan JavaScript API

Kami dapat membalikkan situasi dan menemukan masalah lain di mana pembaruan pada mesin JavaScript browser dapat merusak referensi global elemen bernama.

Sebagai contoh:


  
  
    window.BarcodeDetector.focus();
  

Skrip itu mengambil referensi ke elemen input dan memanggil focus() di atasnya. Ia bekerja dengan benar. Tetap saja, kami tidak tahu caranya panjang itu akan terus bekerja.

Anda lihat, variabel global yang kami gunakan untuk referensi elemen input akan berhenti bekerja segera setelah browser mulai mendukung BarcodeDetector API. Pada saat itu, window.BarcodeDetector global tidak akan lagi menjadi referensi ke elemen input dan .focus() akan melempar โ€œwindow.BarcodeDetector.focus bukan kesalahan fungsiโ€.

Bonus: Tidak semua elemen bernama menghasilkan referensi global

Ingin mendengar sesuatu yang lucu? Untuk menambahkan penghinaan pada cedera, elemen bernama dapat diakses sebagai variabel global hanya jika nama tidak mengandung apa-apa selain huruf. Browser tidak akan membuat referensi global untuk elemen dengan ID yang berisi karakter dan angka khusus, seperti hello-world dan item1.

Kesimpulan

Mari kita simpulkan bagaimana kita sampai di sini:

  • Semua browser utama secara otomatis membuat referensi global untuk setiap elemen DOM dengan id (atau, dalam beberapa kasus, a name atribut).
  • Mengakses elemen-elemen ini melalui referensi globalnya tidak dapat diandalkan dan berpotensi berbahaya. Menggunakan querySelector or getElementById sebagai gantinya.
  • Karena referensi global dibuat secara otomatis, referensi tersebut mungkin memiliki beberapa efek samping pada kode Anda. Itu alasan bagus untuk menghindari penggunaan id atribut kecuali Anda benar-benar membutuhkannya.

Pada akhirnya, mungkin ada baiknya untuk menghindari penggunaan global bernama dalam JavaScript. Saya mengutip spesifikasi sebelumnya tentang bagaimana hal itu mengarah ke kode "rapuh", tetapi inilah teks lengkap untuk mengarahkan intinya ke rumah:

Sebagai aturan umum, mengandalkan ini akan menyebabkan kode rapuh. ID mana yang akhirnya dipetakan ke API ini dapat bervariasi dari waktu ke waktu, karena fitur baru ditambahkan ke platform web, misalnya. Alih-alih ini, gunakan document.getElementById() or document.querySelector().

Saya pikir fakta bahwa spesifikasi HTML itu sendiri merekomendasikan untuk menjauh dari fitur ini berbicara sendiri.

Stempel Waktu:

Lebih dari Trik CSS