Mengapa memperpanjang prototipe objek DOM / built-in adalah ide yang buruk?

15

Saya mencari jawaban yang pasti mengapa memperluas prototipe built-in sangat berat di komunitas pengembang JS. Saya telah menggunakan kerangka JS Prototipe untuk sementara waktu, dan bagi saya melakukan [1,2,3].each(doStuff)tampak jauh lebih elegan daripada $.each([1,2,3], doStuff). Saya tahu bahwa itu menciptakan "polusi namespace," tapi saya masih tidak mengerti mengapa itu dianggap sebagai hal yang buruk. Juga apakah ada penurunan kinerja nyata yang terkait dengan perluasan prototipe bawaan? Terima kasih!

lxe
sumber
1
Satu hal adalah bahwa for(var ... in ...)loop menjadi kacau karena fungsi prototipe dilewatkan juga.
pimvdb
4
"sangat dihukum", benarkah ?! Ya Tuhan, Bung:] Apakah kamu baik-baik saja?
pixelbobby

Jawaban:

12

Saya menyarankan Anda untuk membaca artikel ini yang saya pikir menjelaskan dengan cukup baik mengapa memperluas objek adalah ide yang buruk, berkaitan dengan Prototipe juga.

Singkatnya:

Kurangnya spesifikasi

Paparan "objek prototipe" bukan bagian dari spesifikasi apa pun. [...] Agar implementasi sepenuhnya sesuai dengan DOM Level 2, tidak perlu mengekspos objek Node, Elemen, HTMLElement, dll. Global tersebut.

Objek host tidak memiliki aturan

Objek DOM adalah objek host [...] Objek host dapat mengimplementasikan metode internal ini dengan perilaku tergantung implementasi apa pun, atau mungkin objek host hanya mengimplementasikan beberapa metode internal dan bukan yang lain.

[...] Perilaku metode internal bergantung pada implementasi. [...] Menurut definisi, Anda bekerja dengan sesuatu yang diizinkan berperilaku dengan cara yang tidak dapat diprediksi dan sepenuhnya tidak menentu.

Peluang tabrakan

Mengingat sejumlah besar lingkungan yang digunakan saat ini, menjadi tidak mungkin untuk mengetahui apakah properti tertentu belum menjadi bagian dari DOM. [...]

Setiap kontrol nama bentuk bayangan properti diwarisi melalui rantai prototipe. Peluang tabrakan dan kesalahan tak terduga pada elemen formulir bahkan lebih tinggi.

Mempekerjakan semacam strategi awalan dapat mengatasi masalah tersebut. Tetapi mungkin juga akan membawa suara ekstra.

Overhead kinerja

[...] browser yang tidak mendukung ekstensi elemen — seperti IE 6, 7, Safari 2.x, dll — memerlukan ekstensi objek manual. Masalahnya adalah ekstensi manual lambat, tidak nyaman, dan tidak berskala.

[...] setelah Anda mulai memperluas elemen, API perpustakaan kemungkinan besar perlu mengembalikan elemen yang diperluas ke mana-mana. Akibatnya, metode kueri seperti $$ dapat memperpanjang setiap elemen dalam kueri.

IE DOM berantakan

Seperti yang ditunjukkan pada bagian sebelumnya, ekstensi DOM manual berantakan. Tetapi ekstensi DOM manual di IE bahkan lebih buruk [...]

Bonus: bug browser

Jose Faeti
sumber
9

Alasan lain adalah keterbacaan kode / pemeliharaan. Jika pengembang lain (terutama pemula) membaca kode saya dan melihat [0, 1, 2].foo(...), mereka mungkin tidak tahu apa metode foo atau di mana menemukan dokumentasi / sumber untuk itu. Apakah foo adalah ekstensi ke bahasa yang ditambahkan oleh prototype.js, atau oleh perpustakaan lain yang digunakan, atau oleh bagian lain dari kode saya di file lain, atau apakah itu metode JavaScript asli yang tidak mereka ketahui? Mereka perlu mencari dan mungkin tidak segera menemukannya (atau jika ada konflik mereka mungkin tidak menemukannya).

Dengan pendekatan jQuery, jika Anda lihat $.foo(...), namespace dari metode foo memperjelas di mana menemukan definisi / dokumentasinya jika Anda tidak tahu apa fungsinya.

Bruce Harris
sumber
Keterjangkauan dari mana metode berasal sangat penting bagi pembaca. Meskipun saya tidak benar-benar berpikir jQuery adalah contoh yang baik karena tanda dolar adalah pencarian yang menantang ketika Anda mulai membaca kode web dan belum tahu apa itu.
Simon Feltman
4

Inilah masalah dasarnya: Apa yang terjadi jika Anda memiliki dua alat yang memperpanjang prototipe dengan cara yang tidak kompatibel, atau yang memperluas metode yang biasa disebut dengan cara sedemikian rupa sehingga menghasilkan hasil yang berbeda (ini adalah masalah khusus untuk for...inJavaScript), sehingga menyebabkan kode yang bergantung pada pada perilaku normal mereka untuk istirahat?

Pada dasarnya, ini adalah masalah yang sama yang Anda miliki ketika Anda salah menggunakan variabel global. Dengan sendirinya, mungkin tidak ada hal buruk yang terjadi. Tapi, itu membuka Anda untuk masalah ketika dua potong kode yang seolah-olah terpisah tiba-tiba menginjak satu sama lain (dan itu menyebalkan untuk debug ketika itu terjadi).

Tentu saja prototype.js cukup terkenal dan sebagian besar alat mengatasi apa yang dilakukannya. Demikian pula, saya yakin ada kasus di mana memperluas prototipe basis adalah hal yang benar untuk dilakukan. Tapi, itu sesuatu untuk didekati dengan hati-hati.


sumber
1

Tidak yakin apakah ini benar-benar masih menjadi masalah lagi, tetapi pengalaman saya dengan versi Internet Explorer yang lebih lama adalah bahwa kadang-kadang bahkan tidak mungkin untuk memperluas tipe bawaan tertentu.


sumber
1

Ada dua masalah terpisah di sini. Yang pertama adalah perluasan umum prototipe bawaan, dan lainnya khusus memperluas prototipe DOM. Argumen terhadap perluasan prototipe bawaan:

  • Potensi bentrokan: dua potong kode dari sumber yang berbeda, keduanya mendefinisikan properti yang sama pada prototipe yang sama
  • Efek samping: memperluas Array.prototypeatau Object.prototypedapat memiliki efek knock-on, seperti menambahkan metode ekstensi yang disebutkan dalam satu for...inlingkaran

Adapun memperluas prototipe DOM, argumen potensi bentrokan di atas masih berlaku. Selain itu, node DOM adalah objek host dan karenanya tidak tunduk pada aturan normal objek JavaScript asli. Mereka pada dasarnya dapat melakukan apa yang mereka suka dan tidak berkewajiban untuk menyediakan objek prototipe yang masuk akal atau bahkan mengizinkan properti ekstra ("expando"). IE dalam latihan khusus hak ini, tidak menyediakan prototipe untuk DOM objek sebelum IE 9 dan memiliki berbagai weirdnesses tentang properti di berbagai objek DOM (meskipun Anda properti menugaskan umumnya OK untuk elemen, yang disediakan set apa-apa ini document.expandoke false.)

Tim Down
sumber