Mengapa dokumen. Menulis dianggap sebagai "praktik buruk"?

363

Saya tahu document.writedianggap praktik buruk; dan saya berharap untuk menyusun daftar alasan untuk tunduk kepada vendor pihak ke-3 tentang mengapa mereka tidak boleh digunakan document.writedalam implementasi kode analitik mereka.

Harap sertakan alasan Anda untuk mengklaim document.writesebagai praktik buruk di bawah ini.

FlySwat
sumber

Jawaban:

243

Beberapa masalah yang lebih serius:

  • document.write (selanjutnya DW) tidak berfungsi di XHTML

  • DW tidak secara langsung memodifikasi DOM, mencegah manipulasi lebih lanjut (mencoba untuk menemukan bukti tentang ini, tetapi paling baik situasional)

  • DW dijalankan setelah halaman selesai memuat akan menimpa halaman, atau menulis halaman baru, atau tidak berfungsi

  • DW dieksekusi ketika ditemui: ia tidak dapat menyuntikkan pada titik simpul tertentu

  • DW secara efektif menulis teks berseri yang bukan cara DOM bekerja secara konseptual, dan merupakan cara mudah untuk membuat bug (.innerHTML memiliki masalah yang sama)

Jauh lebih baik menggunakan metode manipulasi DOM yang aman dan ramah DOM

annakata
sumber
39
-1, ini benar-benar memodifikasi DOM. Yang lainnya baik-baik saja. Sementara saya memahami keinginan untuk bergantung pada struktur dan metode yang dapat mencegah Anda dari bahaya, ini mungkin kasus membuang bayi dengan air mandi.
cgp
7
FireBug bukanlah representasi sebenarnya dari DOM. Ini adalah upaya mozilla untuk mem-parsing HTML ke dalam DOM. Anda dapat memiliki tampilan HTML yang benar-benar rusak dalam tampilan Firebug DOM.
FlySwat
8
DOM adalah struktur data yang digunakan untuk me-render halaman dan karena itu adalah alpha dan omega dari apa yang dilihat pengguna pada halaman tersebut. Anda benar bahwa HTML! = DOM, tetapi tidak material untuk pertanyaan apakah DOM TIDAK dimodifikasi oleh DW. Jika DW tidak mengubah DOM, Anda tidak melihat layar - itu berlaku untuk semua browser dan akan selalu selama DOM adalah apa yang digunakan untuk membuat halaman.
cgp
8
"DW mengeksekusi di mana ditemui" - tidak selalu merugikan, memang itu dapat dianggap sebagai keuntungan untuk hal-hal tertentu, misalnya, menambahkan elemen skrip (sebenarnya tentang satu-satunya hal yang saya gunakan untuk DW, dan bahkan kemudian saya akan berpikir dua kali) .
nnnnnn
7
@RicardoRivaldo Ya, benar, jika document.writedipanggil setelah dokumen selesai dimuat
Izkata
124

Sebenarnya tidak ada yang salah dengan itu document.write. Masalahnya adalah sangat mudah untuk menyalahgunakannya. Terlalu, bahkan.

Dalam hal vendor yang memasok kode analitik (seperti Google Analytics) sebenarnya cara termudah bagi mereka untuk mendistribusikan cuplikan tersebut

  1. Itu membuat skrip kecil
  2. Mereka tidak perlu khawatir tentang mengesampingkan peristiwa onload yang telah ditetapkan atau termasuk abstraksi yang diperlukan untuk menambahkan peristiwa onload dengan aman
  3. Ini sangat kompatibel

Selama Anda tidak mencoba menggunakannya setelah dokumen dimuat , padadocument.writedasarnya tidak jahat, menurut pendapat saya.

Peter Bailey
sumber
3
document.write melakukan hal-hal yang sangat mengerikan bagi parser html, dan hanya "sangat kompatibel" dalam kasus sederhana.
olliej
27
Suka penyisipan tag analitik? Bagaimanapun, itu adalah bagian dari pertanyaan awal. Dan dengan sangat kompatibel, maksud saya hanya dukungan browser mentah untuk metode document.write.
Peter Bailey
Apa pun yang berfungsi dengan versi terbaru Chrome / IE / Safari / Opera / FireFox dianggap kompatibel.
Pacerier
2
Mengganti acara yang dimuat? Dan untuk apa addEventListener?
m93a
Chrome tidak akan menjalankan document.writepermintaan yang memasukkan skrip ketika kondisi tertentu terpenuhi.
Flimm
44

Penggunaan sah lainnya document.writeberasal dari contoh HTML5 Boilerplate index.html .

<!-- Grab Google CDN's jQuery, with a protocol relative URL; fall back to local if offline -->
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.6.3/jquery.min.js"></script>
<script>window.jQuery || document.write('<script src="js/libs/jquery-1.6.3.min.js"><\/script>')</script>

Saya juga melihat teknik yang sama untuk menggunakan json2.js JSON parse / stringify polyfill ( diperlukan oleh IE7 dan di bawah ).

<script>window.JSON || document.write('<script src="json2.js"><\/script>')</script>
Kevin Hakanson
sumber
11
Tidak buruk digunakan di sini, tetapi masih "lebih baik" untuk menggunakan fungsi manipulasi DOM - bahkan Google melakukannya untuk Google Analytics. Cuplikan ada di sini .
BMiner
8
@BMiner jika Anda memasukkan scriptelemen melalui manipulasi DOM, apakah itu dimuat secara sinkron? Kecuali itu, itu bukan pengganti.
John Dvorak
2
@JanDvorak - Poin bagus; saat menggunakan manipulasi DOM, browser umumnya akan memuat skrip secara asinkron. Anda dapat menggunakan onloadacara DOM untuk menentukan kapan skrip yang dimuat secara asinkron tersedia untuk digunakan.
BMiner
1
@ JanDvorak Dimuat secara sinkron jika tidak eksternal (tidak ada src) . Kalau tidak, itu akan dieksekusi "sesegera mungkin", asinkron.
Oriol
1
Ini masih bisa putus, karena Chrome akan dengan sengaja menolak untuk menjalankan document.writepanggilan yang menyisipkan <script>tag jika pengguna menggunakan koneksi 2G. Lihat developers.google.com/web/updates/2016/08/…
Flimm
42

Itu dapat memblokir halaman Anda

document.writehanya berfungsi saat halaman dimuat; Jika Anda memanggilnya setelah halaman selesai memuat, itu akan menimpa seluruh halaman.

Ini secara efektif berarti Anda harus memanggilnya dari blok skrip sebaris - Dan itu akan mencegah browser memproses bagian-bagian halaman berikutnya. Script dan Gambar tidak akan diunduh sampai blok penulisan selesai.

Sean McMillan
sumber
32

Pro:

  • Ini cara termudah untuk menyematkan konten sebaris dari skrip eksternal (ke host / domain Anda).
  • Anda dapat menimpa seluruh konten dalam bingkai / iframe. Saya biasa menggunakan teknik ini banyak untuk potongan menu / navigasi sebelum teknik Ajax lebih modern tersedia secara luas (1998-2002).

Menipu:

  • Ini serialisasi mesin rendering untuk berhenti sampai skrip eksternal tersebut dimuat, yang bisa memakan waktu lebih lama dari skrip internal.
  • Biasanya digunakan sedemikian rupa sehingga skrip ditempatkan dalam konten, yang dianggap sebagai bentuk buruk.
Pelacak1
sumber
3
Ada lebih banyak kontra dari itu. Misalnya, Google Chrome akan menolak untuk menjalankan document.writeyang membuat <script>tag dalam keadaan tertentu. developers.google.com/web/updates/2016/08/...
Flimm
@ Flimm perlu dicatat, komentar Anda lebih dari 8 tahun setelah jawaban saya dan ini hampir 3 tahun kemudian. Ya, ada kontra lain ... dan saya akan terkejut jika dokumen. Menulis sendiri tidak hilang ... dan mungkin beberapa antarmuka yang sangat disalahgunakan lainnya.
Tracker1
10

Inilah nilai dua kali lipat saya, secara umum Anda tidak harus menggunakan document.writeuntuk mengangkat berat, tetapi ada satu contoh di mana itu pasti berguna:

http://www.quirksmode.org/blog/archives/2005/06/three_javascrip_1.html

Saya menemukan ini baru-baru ini mencoba membuat galeri slider AJAX. Saya membuat dua div bersarang, dan menerapkan width/ heightdan overflow: hiddenke luar <div>dengan JS. Hal ini dimaksudkan agar seandainya browser menonaktifkan JS, div akan mengambang untuk mengakomodasi gambar-gambar di galeri - beberapa penurunan yang bagus.

Masalahnya, seperti dengan artikel di atas, pembajakan JS ini dari CSS tidak muncul sampai halaman dimuat, menyebabkan flash sesaat ketika div dimuat. Jadi saya perlu menulis aturan CSS, atau memasukkan lembar, saat halaman dimuat.

Jelas, ini tidak akan bekerja di XHTML, tetapi karena XHTML tampaknya seperti bebek mati (dan menjadikannya sebagai sup tag di IE), mungkin perlu mengevaluasi kembali pilihan DOCTYPE Anda ...

sunwukung
sumber
7

Itu menimpa konten pada halaman yang merupakan alasan paling jelas tapi saya tidak akan menyebutnya "buruk".

Itu tidak memiliki banyak kegunaan kecuali Anda membuat seluruh dokumen menggunakan JavaScript dalam hal ini Anda dapat mulai dengan document.write.

Meski begitu, Anda tidak benar-benar memanfaatkan DOM ketika Anda menggunakan document.write - Anda hanya membuang gumpalan teks ke dalam dokumen jadi saya akan mengatakan itu bentuk yang buruk.

aleemb
sumber
2
Satu klarifikasi: document.write menyisipkan konten pada halaman, itu tidak menimpa mereka.
Peter Dolberg
5
@ Peter, itu menimpa konten jika Anda memanggilnya setelah dokumen dimuat. Kurasa itulah arti aleemb.
Matthew Crumley
2
Apakah Anda menyarankan agar seseorang secara manual membangun masing-masing node DOM dalam kode daripada hanya melakukan sesuatu seperti div.innerHTML = "<label for='MySelect'>Choose One</label><select id='MySelect'><option value='foo' selected=''>foo</option><option value='bar'>bar</option></select>";? Sepertinya itu akan menghasilkan banyak kode yang tidak perlu dan kurang dapat dibaca. Ini juga kebalikan dari pendekatan John Resig dan pengembang JS lainnya.
Lèse majesté
7

Memecah halaman menggunakan rendering XML (seperti halaman XHTML).

Terbaik : beberapa browser beralih kembali ke rendering HTML dan semuanya berfungsi dengan baik.

Kemungkinan : beberapa browser menonaktifkan fungsi document.write () dalam mode rendering XML.

Terburuk : beberapa browser akan memunculkan kesalahan XML setiap kali menggunakan fungsi document.write ().

Vincent Robert
sumber
6

Dari atas kepala saya:

  1. document.writeperlu digunakan dalam memuat halaman atau memuat tubuh. Jadi, jika Anda ingin menggunakan skrip di waktu lain untuk memperbarui dokumen konten halaman Anda. Menulis tidak berguna.

  2. Secara teknis document.writehanya akan memperbarui halaman HTML bukan XHTML / XML. IE tampaknya cukup memaafkan fakta ini, tetapi browser lain tidak akan.

http://www.w3.org/MarkUp/2004/xhtml-faq#docwrite

brendan
sumber
9
IE memaafkan karena tidak mendukung XHTML. Jika / ketika mereka melakukannya, document.write mungkin akan berhenti bekerja (hanya di XHTML saja)
Matthew Crumley
2
XHTML tidak relevan di web. Halaman bahkan dengan doctype XHTML ketat tidak benar-benar diperlakukan sebagai XML dalam hal itu, pengembang browser tidak percaya penulis halaman yang banyak.
RobG
4

Chrome dapat memblokir document.writeyang menyisipkan skrip dalam kasus tertentu. Ketika ini terjadi, itu akan menampilkan peringatan ini di konsol:

Skrip pemblokiran, skrip asal-asal, ..., dipanggil melalui document.write. Ini dapat diblokir oleh browser jika perangkat memiliki konektivitas jaringan yang buruk.

Referensi:

TrueWill
sumber
3

Pelanggaran Browser

.writedianggap sebagai pelanggaran browser karena menghentikan pengurai dari membuat halaman. Parser menerima pesan bahwa dokumen sedang diubah; karenanya, ia diblokir sampai JS telah menyelesaikan prosesnya. Hanya pada saat ini parser akan melanjutkan.

Performa

Konsekuensi terbesar dari penggunaan metode semacam itu adalah penurunan kinerja. Browser akan membutuhkan waktu lebih lama untuk memuat konten halaman. Reaksi yang merugikan pada waktu pemuatan tergantung pada apa yang ditulis ke dokumen. Anda tidak akan melihat banyak perbedaan jika Anda menambahkan <p>tag ke DOM sebagai lawan melewati array 50-beberapa referensi ke perpustakaan JavaScript (sesuatu yang saya lihat dalam kode kerja dan menghasilkan penundaan 11 detik - dari tentu saja, ini juga tergantung pada perangkat keras Anda).

Secara keseluruhan, yang terbaik adalah menjauhi metode ini jika Anda dapat membantu.

Untuk info lebih lanjut lihat Melakukan intervensi terhadap document.write ()

Arielle Adams
sumber
3

Berdasarkan analisis yang dilakukan oleh Audit Mercusuar Google-Chrome Dev Tools ' ,

Untuk pengguna dengan koneksi lambat, skrip eksternal yang secara dinamis disuntikkan melalui document.write()dapat menunda pemuatan halaman dengan puluhan detik.

masukkan deskripsi gambar di sini

Sudip Bhandari
sumber
2
  • Alasan sederhana mengapa document.writeini merupakan praktik yang buruk adalah bahwa Anda tidak dapat menemukan skenario di mana Anda tidak dapat menemukan alternatif yang lebih baik.
  • Alasan lain adalah bahwa Anda berurusan dengan string, bukan objek (itu sangat primitif).
  • Itu hanya menambah dokumen.
  • Ini tidak memiliki keindahan seperti pola MVC (Model-View-Controller) .
  • Jauh lebih hebat untuk menyajikan konten dinamis dengan ajax + jQuery atau angularJS .
Anders Lindén
sumber
Mengenai peluru pertama Anda, bagaimana Anda akan menyelesaikan apa yang @sunwukung jelaskan dalam jawaban di atas? Saya setuju Anda bisa menyelesaikannya dengan manipulasi DOM, tetapi ketika manipulasi DOM berjalan, sulit untuk menghindari FUOC di waktu tanpa document.write.
bert bruynooghe
Apakah FUOC masalah lagi?
Anders Lindén
1

Orang dapat menganggap document.write () (dan .innerHTML) sebagai mengevaluasi string kode sumber. Ini bisa sangat berguna untuk banyak aplikasi. Misalnya jika Anda mendapatkan kode HTML sebagai string dari beberapa sumber, akan sangat mudah untuk hanya "mengevaluasi" itu.

Dalam konteks Lisp, manipulasi DOM akan seperti memanipulasi struktur daftar, misalnya membuat daftar (oranye) dengan melakukan:

(cons 'orange '())

Dan document.write () akan seperti mengevaluasi string, misalnya membuat daftar dengan mengevaluasi string kode sumber seperti ini:

(eval-string "(cons 'orange '())")

Lisp juga memiliki kemampuan yang sangat berguna untuk membuat kode menggunakan manipulasi daftar (seperti menggunakan "gaya DOM" untuk membuat pohon parse JS). Ini berarti Anda dapat membangun struktur daftar menggunakan "gaya DOM", bukan "gaya string", dan kemudian jalankan kode itu, misalnya seperti ini:

(eval '(cons 'orange '()))

Jika Anda menerapkan alat pengkodean, seperti editor langsung sederhana, sangat berguna untuk memiliki kemampuan untuk mengevaluasi string dengan cepat, misalnya menggunakan document.write () atau .innerHTML. Lisp ideal dalam hal ini, tetapi Anda dapat melakukan hal-hal yang sangat keren juga di JS, dan banyak orang melakukannya, seperti http://jsbin.com/

Mikael Kindborg
sumber
1

Kerugian dari dokumen. Menulis terutama tergantung pada 3 faktor ini:

a) Implementasi

Document.write () sebagian besar digunakan untuk menulis konten ke layar segera setelah konten itu diperlukan. Ini berarti itu terjadi di mana saja, baik dalam file JavaScript atau di dalam tag skrip dalam file HTML. Dengan tag skrip ditempatkan di mana saja di dalam file HTML seperti itu, adalah ide yang buruk untuk memiliki pernyataan document.write () di dalam blok skrip yang terkait dengan HTML di dalam halaman web.

b) Rendering

Kode yang dirancang dengan baik pada umumnya akan mengambil konten yang dihasilkan secara dinamis, menyimpannya dalam memori, terus memanipulasinya saat melewati kode sebelum akhirnya dimuntahkan ke layar. Jadi, untuk mengulangi poin terakhir di bagian sebelumnya, membuat konten di tempat mungkin membuat lebih cepat daripada konten lain yang mungkin diandalkan, tetapi mungkin tidak tersedia untuk kode lain yang pada gilirannya mengharuskan konten yang akan diberikan untuk diproses. Untuk mengatasi dilema ini, kita perlu menyingkirkan document.write () dan mengimplementasikannya dengan cara yang benar.

c) Manipulasi yang Tidak Mungkin

Setelah ditulis, selesai dan selesai. Kami tidak dapat kembali untuk memanipulasinya tanpa menggunakan DOM.

pengguna3167857
sumber
1

Saya tidak berpikir menggunakan document.write sama sekali bukan praktik yang baik. Dengan kata sederhana itu seperti tegangan tinggi untuk orang yang tidak berpengalaman. Jika Anda menggunakannya dengan cara yang salah, Anda akan matang. Ada banyak pengembang yang telah menggunakan ini dan metode berbahaya lainnya setidaknya sekali, dan mereka tidak pernah benar-benar menggali kegagalan mereka. Sebaliknya, ketika terjadi kesalahan, mereka hanya menyelamatkan, dan menggunakan sesuatu yang lebih aman. Mereka adalah orang-orang yang membuat pernyataan seperti itu tentang apa yang dianggap sebagai "Praktek Buruk".

Ini seperti memformat hard drive, ketika Anda hanya perlu menghapus beberapa file dan kemudian mengatakan "memformat drive adalah praktik yang buruk".

Edgars WEBHAUS
sumber
-3

Saya pikir masalah terbesar adalah bahwa setiap elemen yang ditulis melalui document.write ditambahkan ke akhir elemen halaman. Itu jarang efek yang diinginkan dengan tata letak halaman modern dan AJAX. (Anda harus ingat bahwa elemen-elemen dalam DOM bersifat sementara, dan ketika skrip dijalankan dapat memengaruhi perilakunya).

Jauh lebih baik untuk menetapkan elemen placeholder di halaman, dan kemudian memanipulasi innerHTML-nya.

BnWasteland
sumber
15
Ini tidak benar. document.write tidak menambahkan konten ke akhir halaman seperti itu menambahkan. Mereka tertulis di tempatnya.
Peter Bailey
1
@ Peter Bailey, saya tahu ini adalah utas lama, tetapi sebenarnya ini tidak seharusnya dibatalkan. apakah itu ditambahkan atau tidak tergantung pada apakah document.write () berjalan inline saat halaman dimuat. Jika dipanggil dari fungsi setelah halaman dimuat maka document.write () pertama akan menggantikan seluruh isi dan panggilan berikutnya akan menambahkannya.
Octopus
3
@ Otopus Ya, tapi itu tidak langsung. Itu ditambahkan dalam skenario itu hanya karena ada dokumen baru. Masih belum akurat untuk mengatakan "document.write () append." Ya, ini adalah jawaban lama dan downvote lama, tapi saya tetap mendukungnya.
Peter Bailey
Tidak apa-apa. Saya berbicara dengan tidak tepat. Saya sudah mengeditnya sejak lama, tetapi ada jawaban yang jauh lebih baik di atas. Saya akan menunjukkan bahwa "tertulis di tempat" sama-sama tidak tepat.
BnWasteland