Document.write neden “kötü uygulama” olarak kabul edilir?


363

document.writeKötü uygulama olarak kabul edildiğini biliyorum ; ve üçüncü taraf bir satıcıya document.write, analitik kodlarının uygulamalarında neden kullanmamaları gerektiğine ilişkin nedenlerin bir listesini derlemeyi umuyorum .

Lütfen document.writeaşağıda kötü bir uygulama olduğunu iddia etme nedeninizi belirtin .

Yanıtlar:


243

Daha ciddi sorunlardan birkaçı:

  • XHTML'de document.write (bundan böyle DW) çalışmıyor

  • DW, DOM'yi doğrudan değiştirmez, daha fazla manipülasyonu önler (bunun kanıtını bulmaya çalışır, ancak en iyi durumda)

  • Sayfanın yüklenmesi bittikten sonra yürütülen DW sayfanın üzerine yazacak veya yeni bir sayfa yazacak veya çalışmıyor

  • DW, karşılaşıldığı yerde yürütür: belirli bir düğüm noktasına enjekte edemez

  • DW, DOM'un kavramsal olarak çalışma şekli olmayan ve hatalar oluşturmanın kolay bir yolu olan serileştirilmiş metinleri etkili bir şekilde yazıyor (.innerHTML'de aynı sorun var)

Güvenli ve DOM dostu DOM manipülasyon yöntemlerini kullanmak çok daha iyi


39
-1, DOM'yi kesinlikle değiştirir. Diğer her şey yolunda. Sizi zarar görmekten koruyabilecek yapıya ve yöntemlere bağımlı olma dürtüsünü anlasam da, bu bebeği banyo suyuyla atmak için bir durum olabilir.
cgp

7
FireBug, DOM'nin gerçek bir temsili değildir. Mozilla'nın HTML'yi bir DOM'a ayrıştırma girişimi. Firebug DOM görünümünde tamamen bozuk HTML görünümüne sahip olabilirsiniz.
sineklik

8
DOM, sayfayı oluşturmak için kullanılan veri yapısıdır ve bu nedenle kullanıcının sayfada gördüklerinin alfa ve omega'sıdır. Bu HTML! = DOM'u haklısınız, ancak DOM'un DW tarafından değiştirilip değiştirilmediği sorusu önemsizdir. DW DOM'yi değiştirmediyse, ekranı görmezsiniz - bu tüm tarayıcılar için geçerlidir ve her zaman DOM, sayfayı oluşturmak için kullanılan şey olduğu sürece olacaktır.
cgp

8
"DW karşılaşılan yerlerde yürütür" - her zaman bir dezavantaj değil, aslında bazı şeyler için bir avantaj olarak düşünülebilir, örneğin komut dosyası öğeleri ekleme (aslında DW için kullanacağım tek şey hakkında ve hatta iki kez düşünürdüm) .
nnnnnn

7
@RicardoRivaldo Evet, document.writebelge yükleme bittikten sonra çağrılırlarsa
izliyorlar

124

Aslında yanlış olan hiçbir şey yoktur document.write. Sorun şu ki, kötüye kullanımı gerçekten kolay. Kesinlikle.

Analiz kodu sağlayan satıcılar (Google Analytics gibi) açısından, aslında bu tür snippet'leri dağıtmanın en kolay yolu

  1. Senaryoları küçük tutar
  2. Zaten kurulmuş onload olaylarını geçersiz kılma veya onload olaylarını güvenli bir şekilde eklemek için gerekli soyutlamayı dahil etme konusunda endişelenmeleri gerekmez
  3. Son derece uyumlu

Sürece belge yüklendikten sonra kullanmaya kalkmayın olarak ,document.writebenim düşünceme göre, doğal olarak kötü değil.


3
document.write, html ayrıştırıcılarına gerçekten korkunç şeyler yapar ve basit durumlarda yalnızca "son derece uyumludur".
olliej

27
Bir analiz etiketinin eklenmesi gibi mi? Ne de olsa orijinal sorunun bir parçası. Ve son derece uyumlu olarak, yani document.write yöntemi için sadece ham tarayıcı desteği demek.
Peter Bailey

Chrome / IE / Safari / Opera / FireFox'un en son sürümleriyle çalışan her şey uyumlu kabul edilir.
Pacerier

2
Yükleme olaylarını geçersiz kılmak istiyor musunuz? Peki ne addEventListeneriçin?
m93a

Chrome, document.writebelirli koşullar karşılandığında komut dosyası ekleyen çağrıları çalıştırmaz .
Flimm

44

Bir başka meşru kullanımı document.writeHTML5 Boilerplate index.html örneğinden gelir.

<!-- 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>

Ben de json2.js JSON ayrıştırma / stringify polifill ( IE7 ve aşağıda gerekli) kullanmak için aynı tekniği gördüm .

<script>window.JSON || document.write('<script src="json2.js"><\/script>')</script>

11
Burada kötü değil, ancak DOM manipülasyon işlevlerini kullanmak için hala "daha iyi" - Google bile Google Analytics için yapıyor. Snippet burada .
BMiner

8
@BMiner scriptDOM manipülasyonu ile bir eleman eklerseniz , senkronize olarak yüklenir mi? Olmadıkça, bir yedek değildir.
John Dvorak

2
@JanDvorak - İyi bir nokta; DOM manipülasyonlarını kullanırken, tarayıcılar genellikle komut dosyasını eşzamansız olarak yükler. Zaman onloaduyumsuz olarak yüklenmiş komut dosyasının ne zaman kullanılabilir olduğunu belirlemek için DOM olayını kullanabilirsiniz.
BMiner

1
@JanDvorak Harici değilse (yoksa src) senkronize olarak yüklenir . Aksi takdirde, eşzamansız olarak "mümkün olan en kısa sürede" yürütülür.
Oriol

1
Chrome , kullanıcı 2G bağlantısındaysa etiket document.writeekleyen aramaları kasıtlı olarak reddedeceğinden bu durum yine de kesilebilir <script>. Bkz developers.google.com/web/updates/2016/08/...
Flimm

42

Sayfanızı engelleyebilir

document.writeyalnızca sayfa yüklenirken çalışır; Sayfanın yüklenmesi tamamlandıktan sonra çağırırsanız, tüm sayfanın üzerine yazılır.

Bu, etkili bir şekilde satır içi komut dosyası bloğundan çağırmanız gerektiği anlamına gelir - Ve bu, tarayıcının aşağıdaki sayfanın bölümlerini işlemesini önler. Komut dosyaları ve Resimler, yazma bloğu bitinceye kadar indirilmez.


31

Pro:

  • Harici (ana makinenize / alan adınıza) bir komut dosyasından satır içi içeriği gömmenin en kolay yolu budur.
  • Bir çerçevedeki / iframe'deki tüm içeriğin üzerine yazabilirsiniz. Daha modern Ajax teknikleri yaygın olarak kullanılmadan önce bu tekniği menü / navigasyon parçaları için çok kullanıyordum (1998-2002).

con:

  • Oluşturma motorunu, söz konusu harici komut dosyası yüklenene kadar duraklatmak üzere serileştirir; bu, bir iç komut dosyasından çok daha uzun sürebilir.
  • Genellikle, komut dosyasının içeriğin içine yerleştirileceği ve kötü biçim olarak kabul edildiği şekilde kullanılır.

3
Bundan daha fazla eksileri var. Örneğin, Google Chrome, belirli koşullarda etiket document.writeoluşturan çalışmayı reddedecektir <script>. developers.google.com/web/updates/2016/08/…
Flimm

@Flimm kayda değer, yorumunuz cevabımdan 8 yıl sonra ve bu neredeyse 3 yıl sonra. Evet, başka dezavantajları var ... ve document.write'ın kendisi gitmezse ... ve muhtemelen diğer son derece kötüye kullanılan arayüzlerden dolayı şaşırırdım.
Tracker1

10

İşte benim twopence değerinde, genel document.writeolarak ağır kaldırma için kullanmamalısınız , ancak kesinlikle yararlı olduğu bir örnek var:

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

Son zamanlarda bir AJAX kaydırıcı galerisi oluşturmaya çalışırken bunu keşfettim. İki iç içe div oluşturdum ve width/ heightve JS ile overflow: hiddendışa uyguladım <div>. Bu, tarayıcının JS'yi devre dışı bırakması durumunda div'ın galerideki görüntüleri barındırmak için yüzer - bazı güzel zarif bozulmalar.

Şey, yukarıdaki makalede olduğu gibi, CSS'nin bu JS ele geçirilmesi sayfa yüklenene kadar devreye girmedi ve div yüklenirken anlık bir flaş oluşmasına neden oldu. Bu yüzden yüklenen sayfa olarak bir CSS kuralı yazmam veya bir sayfa eklemem gerekiyordu.

Açıkçası, bu XHTML'de işe yaramaz, ancak XHTML ölü bir ördek gibi göründüğü için (ve IE'de etiket çorbası olarak işlenir), DOCTYPE seçiminizi yeniden değerlendirmeye değer olabilir ...


7

Sayfadaki içeriğin üzerine yazılan en bariz neden ama ben buna "kötü" demem.

JavaScript kullanarak bir belgenin tamamını oluşturmadığınız sürece çok fazla faydası olmaz, bu durumda document.write ile başlayabilirsiniz.

Yine de, document.write komutunu kullandığınızda DOM'dan gerçekten yararlanmıyorsunuz - belgeye sadece bir metin bloğu döküyorsunuz, bu yüzden kötü form olduğunu söyleyebilirim.


2
Bir açıklama: document.write sayfaya içerik ekler, bunların üzerine yazmaz.
Peter Dolberg

5
@Peter, belge yüklendikten sonra çağırırsanız içeriğin üzerine yazar. Sanırım aleemb bunun anlamı.
Matthew Crumley

2
Bunun yerine tek tek DOM düğümlerini kod gibi manuel olarak yapmak yerine manuel olarak oluşturmanız gerektiğini mi öneriyorsunuz div.innerHTML = "<label for='MySelect'>Choose One</label><select id='MySelect'><option value='foo' selected=''>foo</option><option value='bar'>bar</option></select>";? Bu, gereksiz ve daha az okunabilir kod üretecek gibi görünüyor. Ayrıca John Resig ve diğer JS geliştiricilerinin savunduğu yaklaşımın tam tersi.
Lèse majesté

7

XML oluşturma (XHTML sayfaları gibi) kullanarak sayfaları keser.

En iyi : bazı tarayıcılar HTML oluşturmaya geri döner ve her şey iyi çalışır.

Olası : bazı tarayıcılar XML oluşturma modunda document.write () işlevini devre dışı bırakır.

En kötü : bazı tarayıcılar document.write () işlevini her kullandığında bir XML hatası tetikler.


6

Kafamın üstünden:

  1. document.writesayfa yükünde veya gövde yükünde kullanılması gerekir. Bu nedenle, komut dosyasını başka bir zamanda sayfa içeriği belgenizi güncellemek için kullanmak istiyorsanız.

  2. Teknik olarak document.writeyalnızca XHTML / XML değil HTML sayfalarını güncelleyecektir. IE bu gerçeği oldukça affedici görünüyor ama diğer tarayıcılar olmayacak.

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


9
XHTML'yi desteklemediği için IE affedicidir. Eğer yaparlarsa / yaparlarsa, document.write muhtemelen çalışmayı durduracaktır (sadece XHTML'de).
Matthew Crumley

2
XHTML web üzerinde önemsizdir. Sıkı bir XHTML doktrinine sahip sayfalar bile bu açıdan XML olarak değerlendirilmez, tarayıcı geliştiricileri sayfa yazarlarına o kadar güvenmezler .
RobG

4

Chrome, document.writebelirli durumlarda komut dosyası ekleyen engelleyebilir . Bu olduğunda, konsolda şu uyarıyı görüntüler:

Ayrıştırıcı engelleyen, çapraz kökenli bir komut dosyası, ..., document.write aracılığıyla çağrılır. Cihazın ağ bağlantısı zayıfsa tarayıcı tarafından engellenebilir.

Referanslar:


3

Tarayıcı İhlali

.writeayrıştırıcının sayfayı görüntülemesini durdurduğundan bir tarayıcı ihlali olarak kabul edilir. Ayrıştırıcı, belgenin değiştirildiği mesajını alır; dolayısıyla JS işlemi tamamlanıncaya kadar engellenir. Ayrıştırıcı yalnızca şu anda devam edecektir.

Verim

Böyle bir yöntem kullanmanın en büyük sonucu düşük performanstır. Tarayıcının sayfa içeriğini yüklemesi daha uzun sürer. Yükleme süresindeki olumsuz reaksiyon, belgeye ne yazıldığına bağlıdır. <p>JavaScript kitaplıklarına (bazılarının çalışma kodunda gördüğüm ve 11 saniyelik bir gecikmeyle sonuçlanan bir şey) 50'den fazla referans dizisinin aksine DOM'a bir etiket ekliyorsanız, çok fazla bir fark görmeyeceksiniz . tabii ki, bu da donanımınıza bağlıdır).

Sonuçta, eğer yardımcı olabilirseniz, bu yöntemden uzak durmak en iyisidir.

Daha fazla bilgi için bkz. Document.write () öğesine müdahale


3

Google-Chrome Dev Tools'un Deniz Feneri Denetimi tarafından yapılan analizlere dayanarak ,

Yavaş bağlantı kullanan kullanıcılar için, dinamik olarak enjekte edilen harici komut dosyaları document.write()sayfa yüklemesini on saniye geciktirebilir.

resim açıklamasını buraya girin


2
  • document.writeKötü bir uygulama olmasının basit bir nedeni , daha iyi bir alternatif bulamadığınız bir senaryo bulamamanızdır.
  • Başka bir neden, nesneler yerine dizelerle uğraşmanızdır (çok ilkeldir).
  • Yalnızca belgelere eklenir.
  • Örneğin MVC (Model-View-Controller) modelinin güzelliği yoktur .
  • Ajax + jQuery veya angularJS ile dinamik içerik sunmak çok daha güçlüdür .

İlk merminizin gidişine gelince, yukarıdaki cevapta @sunwukung'un tanımladığı şeyi nasıl çözeceksiniz? Sana katılıyorum olabilir DOM manipülasyonlar ile çözmek, ama DOM manipülasyonları giderken, o olmadan zamanlarda FUOC önlemek zordur document.write.
bert bruynooghe

FUOC artık bir sorun mu?
Anders Lindén

1

Document.write () (ve .innerHTML) 'nin bir kaynak kod dizesini değerlendirdiği düşünülebilir. Bu, birçok uygulama için çok kullanışlı olabilir. Örneğin, HTML kodunu bir kaynaktan dize olarak alırsanız, sadece "değerlendirmek" için kullanışlıdır.

Lisp bağlamında, DOM manipülasyonu bir liste yapısını manipüle etmek gibi olacaktır, örneğin:

(cons 'orange '())

Document.write (), bir dizeyi değerlendirmek gibidir; örneğin, aşağıdaki gibi bir kaynak kodu dizesini değerlendirerek bir liste oluşturun:

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

Lisp ayrıca liste manipülasyonu (JS ayrıştırma ağacı oluşturmak için "DOM stili" kullanmak gibi) kullanarak kod oluşturmak için çok yararlı bir yeteneğe sahiptir. Bu, "dize stili" yerine "DOM stilini" kullanarak bir liste yapısı oluşturabileceğiniz ve ardından bu kodu çalıştırabileceğiniz anlamına gelir, örneğin:

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

Basit canlı editörler gibi kodlama araçlarını uygularsanız, örneğin bir document.write () veya .innerHTML kullanarak bir dizeyi hızlı bir şekilde değerlendirme yeteneğine sahip olmak çok kullanışlıdır. Lisp bu anlamda idealdir, ancak JS'de de çok güzel şeyler yapabilirsiniz ve birçok insan bunu yapıyor, örneğin http://jsbin.com/


1

Belgenin dezavantajları esas olarak şu 3 faktöre bağlıdır:

a) Uygulama

Document.write () çoğunlukla, içerik gerektiğinde ekrana içerik yazmak için kullanılır. Bu, bir JavaScript dosyasında veya bir HTML dosyası içindeki bir komut dosyası etiketinin içinde herhangi bir yerde gerçekleştiği anlamına gelir. Komut dosyası etiketi böyle bir HTML dosyasının herhangi bir yerine yerleştirilirken, komut dosyası bloklarının içinde bir web sayfasının içindeki HTML ile iç içe geçmiş olan document.write () ifadelerinin bulunması kötü bir fikirdir.

b) Oluşturma

İyi tasarlanmış kod genel olarak dinamik olarak oluşturulmuş herhangi bir içeriği alır, hafızada saklar, nihayet ekrana çıkmadan önce koddan geçerken manipüle etmeye devam eder. Dolayısıyla, önceki bölümdeki son noktayı yinelemek için, içeriği yerinde oluşturmak, güvenilebilecek diğer içeriklerden daha hızlı görüntülenebilir, ancak içeriğin işlenmesi için oluşturulmasını gerektiren diğer kod tarafından kullanılamayabilir. Bu ikilemi çözmek için document.write () yönteminden kurtulmalı ve doğru şekilde uygulamalıyız.

c) İmkansız Manipülasyon

Yazıldıktan sonra bitti ve bitti. DOM'ye dokunmadan manipüle etmek için geri dönemeyiz.


1

Document.write komutunu kullanmanın hiç de kötü bir uygulama olduğunu düşünmüyorum. Basit bir deyişle, deneyimsiz insanlar için yüksek bir voltaj gibidir. Yanlış şekilde kullanırsanız, pişirilirsiniz. Bunu ve diğer tehlikeli yöntemleri en az bir kez kullanan birçok geliştirici var ve asla başarısızlıklarına girmiyorlar. Bunun yerine, bir şeyler ters gittiğinde, sadece kurtarırlar ve daha güvenli bir şey kullanırlar. Bunlar "Kötü Uygulama" olarak kabul edilen şey hakkında böyle açıklamalar yapanlardır.

Bu, yalnızca birkaç dosyayı silmeniz ve ardından "sürücüyü biçimlendirmek kötü bir uygulamadır" demeniz gerektiğinde, bir sabit diski biçimlendirmek gibidir.


-3

Bence en büyük sorun, document.write ile yazılan öğelerin sayfanın öğelerinin sonuna eklenmesidir. Modern sayfa düzenleri ve AJAX ile nadiren istenen etki budur. (DOM'daki öğelerin geçici olduğunu ve komut dosyası çalıştığında davranışını etkileyebileceğini unutmayın).

Sayfada bir yer tutucu öğe ayarlamak ve daha sonra bunun innerHTML'sini değiştirmek çok daha iyidir.


15
Bu doğru değil. document.write, içeriği sayfanın sonuna eklenmiş gibi eklemez. Bunlar yerinde yazılmıştır.
Peter Bailey

1
@Peter Bailey, bunun eski bir iş parçacığı olduğunu biliyorum, ama gerçekten bu indirilmemeli. eklenip eklenmeyeceği, sayfa yüklenirken document.write () öğesinin satır içi çalışıp çalışmadığına bağlıdır. Sayfa yüklendikten sonra bir işlevden çağrılırsa, ilk document.write () tüm gövdenin yerini alacak ve sonraki çağrılar buna eklenecektir.
Ahtapot

3
@Octopus Evet, ama bu durumsal. Bu senaryoya yalnızca yeni bir belge olduğu için eklenir. Hala "document.write () eklenir" demek doğru değildir. Evet, bu eski bir cevap ve eski bir aşağı oy, ama hala yanındayım.
Peter Bailey

Bu iyi. Doğru konuşmadım. Bunu uzun zaman önce düzenlerdim, ama yukarıda çok daha iyi bir cevap var. Ben "yerinde yazılmış" eşit kesin değil olsa işaret ediyorum.
BnWasteland
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.