<Script defer = “defer”> tam olarak nasıl çalışır?


208

Birkaç <script>öğe var ve bazılarında kod diğer <script>öğelerdeki koda bağlıdır . deferKod blokları yürütme ertelenmesine izin verir gibi burada kullanışlı gelebilir gördüm .

Bunu test etmek için Chrome'da yürüttüm : http://jsfiddle.net/xXZMN/ .

<script defer="defer">alert(2);</script>
<script>alert(1)</script>
<script defer="defer">alert(3);</script>

Ancak uyarır 2 - 1 - 3. Neden uyarmıyor 1 - 2 - 3?


2
Belki bu makaleye göz atın . Ve her zaman olduğu gibi, IE bir şeyin ne anlama geldiğini kendi alır ve önce komut dosyasını yüklemeye karar verdi, ancak vücut yüklenene kadar yürütmeyi geciktirdi (tipik olarak).
Brad Christie

Ancak, test sayfasının Chrome'da farklı bir sonucu var: websiteoptimization.com/speed/tweak/defer/test . Ekran görüntüsü, nasıl beklediğimi gösterirken, Chrome sadece ertelenmiş gibi görünüyor.
11'te pimvdb

1
IE'nin erteleme tanımını bulacağınızı, W3C'nin DOM Seviye 1 spesifikasyonundaki erteleme niyetiyle eşleşeceğini düşünüyorum.
Mark At Ramp51

41
Alohci'nin cevabında belirttiği gibi, HTML Standardına defer göre sadece belirlerken geçerlidir src. Bu, örneğinizin çoğu tarayıcıda beklendiği gibi çalışmamasının bir nedeni olabilir.
Pankrat

2
@Pankrat Gerçek hikaye! Deneyin jsfiddle.net/xXZMN/50 Firefox24 test edilmiştir
m93a

Yanıtlar:


51

GÜNCELLEME: 2/19/2016

Bu cevabın eski olduğunu düşünün. Daha yeni tarayıcı sürümüyle ilgili bilgi için bu yayındaki diğer yanıtlara bakın.


Temel olarak, erteleme tarayıcıya o komut dosyası bloğunda javascript çalıştırmadan önce "hazır olana kadar" beklemesini söyler. Genellikle bu DOM yükleme ve belgeyi bitirdikten sonra olur .readyState == 4

Erteleme özniteliği Internet Explorer'a özgüdür. Internet Explorer 8'de, Windows 7'de JS Fiddle test sayfanızda gördüğüm sonuç 1 - 2 - 3.

Sonuçlar tarayıcıdan tarayıcıya değişebilir.

http://msdn.microsoft.com/en-us/library/ms533719(v=vs.85).aspx

Popüler inanışın aksine, IE standartları izin verdiğinden daha sık takip eder, gerçekte "erteleme" özelliği DOM Level 1 spec'te tanımlanmıştır http://www.w3.org/TR/REC-DOM-Level-1/level -on-html.html

W3C'nin erteleme tanımı: http://www.w3.org/TR/REC-html40/interact/scripts.html#adef-defer :

"Bu boolean özniteliği ayarlandığında, kullanıcı aracısına komut dosyasının herhangi bir belge içeriği üretmeyeceğine dair bir ipucu sağlar (örn., Javascript'te" document.write "yok) ve böylece kullanıcı aracısı ayrıştırmaya ve oluşturmaya devam edebilir."


8
@ MarkAtRamp51 - Cevabınız güncel değilse, diğer yanıtlardaki yorumlarda aşağı oylardan şikayet etmek yerine onu düzenlemelisiniz. Downvotes, "yararlı olmayan" yanıtlar içindir.
Christian Conkle

10
@ChristianConkle Görgü kuralları dersini takdir ediyorum, ancak buradaki diğer cevaplar güncel. Sorunun sorulduğu sırada yanlış cevabın seçilmediğine değiniyordum. Belki de, insanlara olayların zaman içinde değiştiğini ve bağlamın önemli olduğunu hatırlatmaya çalışan insanlar yerine, yanlış bir şekilde cevaplar seçerek topluluk hakkında yanlış değerlendirmeler yapan insanlara polislik yapmalısınız. Tarihsel bilgiler de değerli olduğu için cevabımı kaldırmanın değerini görmüyorum.
Mark At Ramp51

3
"Geçmiş bilgiler de değerli olduğu için cevabımı kaldırmanın değerini görmüyorum" Bu durumda, başlangıçta yalnızca HTML5 öncesi için geçerli olduğunu ve ardından "doğru" yı ( güncel) cevap? Bu size çok fazla sorun kurtaracaktır (bir kez "yanlış" yanıtı kabul eden ve sonunda değiştirmek için "akran baskısı" olan bir adam olarak konuşmak).
mgibsonbr

3
@Leo işaretlenmemeli mi? "Html5 erteleme komut dosyası" arayarak bu Google'da üçüncü sonuçtur. Bu cevap daha sonra birçok kullanıcıya eski ve yanlış tanımlamalar sağlıyor. (Şu anki tanım: "Kullanıcı aracının komut dosyasının işlenmesini erteleyebileceğini gösterir. HTML 4.0'daki erteleme öznitelik tanımına bakın.").
Malavos

2
Cevabınızı güncellemeniz gerektiğini düşünüyorum. Bu soruyu bulan ve cevabınızı bulan herkes, geçmiş bilgilerini tanımayacaktır. Onlara bugün doğru olan cevap gibi görünecek. İnternet böyle çalışır. Bu yüzden cevabınızı düzenlemelisiniz, bir zamanlar doğru olduğunu not etmeli ve doğru cevaba bakınız.
Juuro

167

HTML5 spesifikasyonundan birkaç snippet: http://w3c.github.io/html/semantics-scripting.html#element-attrdef-script-async

Src özelliği yoksa erteleme ve zaman uyumsuzluk özellikleri belirtilmemelidir.


Bu öznitelikler [async ve ertele] kullanılarak seçilebilecek üç olası mod vardır. Zaman uyumsuzluk özelliği varsa, komut dosyası kullanılabilir olduğu anda senkronize olmayan bir şekilde yürütülür. Eşzamansız özniteliği yoksa ancak erteleme özniteliği varsa, sayfa ayrıştırmayı tamamladığında komut dosyası yürütülür. Her iki özellik de mevcut değilse, kullanıcı aracısı sayfayı ayrıştırmaya devam etmeden önce komut dosyası hemen alınır ve yürütülür.


Bu öznitelikler için kesin işleme ayrıntıları, çoğunlukla tarihsel nedenlerden dolayı, HTML'nin çeşitli yönlerini içeren biraz önemsizdir. Dolayısıyla uygulama gereklilikleri şartname boyunca dağılmıştır. Aşağıdaki algoritmalar (bu bölümde) bu işlemenin çekirdeğini açıklamaktadır, ancak bu algoritmalar HTML'de, yabancı içerikte ve XML'de script.write için komut dosyası başlangıç ​​ve bitiş etiketleri için ayrıştırma kurallarına başvurmaktadır. () yöntemi, komut dosyasının işlenmesi vb.


Öğenin src özniteliği varsa ve öğenin erteleme özniteliği varsa ve öğe "ayrıştırıcıya eklenen" olarak işaretlenmişse ve öğenin zaman uyumsuz bir özniteliği yoksa:

Öğe, belgeyi öğeyi oluşturan ayrıştırıcının Belgesi ile ilişkili ayrıştırma bittiğinde yürütülecek olan komut dosyası listesinin sonuna eklenmelidir.


37
Belki, buradaki cevabım, yararlı olmayan yorumunuz nedeniyle insanların cevabımı oylamalarını engelleyecektir. Kabul edilen cevap yanlış değil, cevap farklı, çünkü 2011'in başlarında HTML5 spesifikasyonu ana akım web tarayıcıları için şu anda olduğundan daha az alakalı. Bu cevap daha iyi olabilir, ancak kabul edilen cevap herhangi bir standart tarafından YANLIŞ değildir .
Mark At Ramp5151

3
Spesifikasyonun ne dediğini bilmek yararlı olsa da, IE <9 gibidefer bazı tarayıcıların kötü uyguladığı ortaya çıkıyor . Eğer kullanırsanız defer, size komut dosyaları bazı tarayıcılarda sırayla yürütülmektedir güvenemez.
Flimm

2
@Flimm Sadece IE değil, aynı zamanda Firefox'ta da yürütme sırası garanti edilmiyor gibi görünüyor .
Franklin Yu

İlk teklif artık geçerli değil mi? Şimdi bunu okuyabilirim: "src özniteliği yoksa veya komut dosyası klasik bir komut dosyası değilse, öznitelik belirtilmemelidir." Klasik bir komut dosyası da src = "" içermeyen bir komut dosyasıdır.
Félix Sanz

158

Asıl cevap şudur: Çünkü ertelemeye güvenemezsiniz.

Kavramda erteleme ve zaman uyumsuzluk şu şekilde farklılık gösterir:

async , komut dosyasının engellemeden arka planda indirilmesine izin verir. Ardından, indirmeyi tamamladığı an, oluşturma engellenir ve bu komut dosyası yürütülür. Komut dosyası yürütüldüğünde işleme devam eder.

defer , komut dosyalarının sayfada belirtildikleri sırayla yürütülmesini ve belgenin ayrıştırma bittikten sonra yürütüleceğini garanti eden iddialar dışında aynı şeyi yapar. Bu nedenle, bazı komut dosyaları indirmeyi bitirip daha sonra indirilen, ancak önlerinde görünen komut dosyalarını bekleyebilir ve bekleyebilir.

Ne yazık ki, gerçekten kedi dövüşü standartlarından dolayı, ertelemenin tanımı spesifikasyona göre değişir ve en son spesifikasyonlarda bile yararlı bir garanti sunmaz. Buradaki yanıtların ve bu sorunun gösterdiği gibi, tarayıcılar ertelemeyi farklı uygular:

  • Bazı durumlarda, bazı tarayıcılarda deferkomut dosyalarının bozulmasına neden olan bir hata vardır .
  • Bazı tarayıcılar DOMContentLoadedolayı deferkomut dosyaları yükleninceye kadar erteler, bazıları istemez.
  • Bazı tarayıcılar itaat deferüzerinde <script>satır içi koduyla ve olmayan unsurları srcözniteliği ve bazı görmezden.

Neyse ki spec en azından asenkronun geçersiz kılmayı ertelediğini belirtiyor. Böylece tüm komut dosyalarını zaman uyumsuz olarak ele alabilir ve aşağıdaki gibi geniş bir tarayıcı desteği alabilirsiniz:

<script defer async src="..."></script>

Dünya genelinde kullanılan tarayıcıların% 98'i ve ABD'de% 99'u bu yaklaşımla engellenmekten kaçınacaktır.

(Belgenin ayrıştırılması bitinceye kadar beklemeniz gerekiyorsa, etkinlik DOMContentLoadedolayını dinleyin veya jQuery'nin kullanışlı .ready()işlevini kullanın . Bunu, hiç uygulanmayan tarayıcılara zarif bir şekilde geri dönmek için yine de yapmak istersiniz defer.)


13
Teşekkürler, cevabınız benim için en faydalı oldu!
markus

5
Bunun yanlış olduğuna inanıyorum. Ertelemenin yararı, sayfanın ayrıştırılması tamamlanana kadar yürütülmemesidir. Bu sayfa zaman uyumsuz ve erteleme arasındaki farkı açıklamak için iyi bir görsel var: peter.sh/experiments/…
tinkerr

1
@tinkerr Kavramda haklısınız; pratikte bu doğru değildir. Tutarlı bir şekilde uygulanmadığından, dizi garantisi evrensel değildir ve bu nedenle bir garanti değildir. Bir şeyi uygularken yürütmeyi önemsiyorsunuz. Tasarımın amacı sevimli, ama özellikle yararlı değil.
Chris Moschini

Opera'nın bu deferözelliği 2 Haziran 2013'te yayınlanan 15 sürümünden beri desteklediğini belirtmek istedim .

1
@VikasBansal Zaman uyumsuzluğu (eski IE) desteklemeyen eski tarayıcılar için.
Chris Moschini

13

defer<script>etiketi yalnızca harici komut dosyası eklenmesi için kullanılabilir . Bu nedenle, <script>-bölümündeki -tag'lerde kullanılması önerilir <head>.


8

Erteleme özelliği yalnızca src ile komut dosyası etiketi ile çalışır. Satır içi komut dosyaları için ertelemeyi taklit etmenin bir yolunu buldu. DOMContentLoaded olayını kullanın.

<script defer src="external-script.js"></script>
<script>
document.addEventListener("DOMContentLoaded", function(event) {
    // Your inline scripts which uses methods from external-scripts.
});
</script>

Bunun nedeni, ertelenen ilişkilendirilmiş komut dosyaları tamamen yüklendikten sonra DOMContentLoaded olayının tetiklenmesidir.


6

Erteleme özelliği yalnızca harici komut dosyaları içindir (yalnızca src özelliği varsa kullanılmalıdır).



4

Bu mükemmel makaleye bir göz atın 2013 yılında yazılmış Google geliştiricisi Jake Archibald'ın senaryo yüklemesinin bulanık sularına derinlemesine dalın .

Bu bölümdeki ilgili bölümden alıntı:

ertele

<script src="//other-domain.com/1.js" defer></script>
<script src="2.js" defer></script>

Spec diyor ki : Birlikte indirin, DOMContentLoaded'den hemen önce sırayla yürütün. "Src" olmadan komut dosyalarındaki "erteleme" yi yok sayın.

IE <10 diyor ki : 1.js 1.js yürütme yoluyla yarıda yürütmek. Eğlenceli değil mi ??

Kırmızı tarayıcılar şöyle diyor : Bu “erteleme” olayının ne olduğu hakkında hiçbir fikrim yok, scriptleri orada değilmiş gibi yükleyeceğim.

Diğer tarayıcılar şöyle der : Tamam, ancak "src" olmadan komut dosyalarındaki "erteleme" yi görmezden gelmeyebilirim.

( Bu yoruma göre , Firefox'un ilk sürümlerinin deferkomut dosyalarının çalışması bitmeden DOMContentLoaded'i tetiklediğini ekleyeceğim .)

Modern tarayıcılar asyncdüzgün bir şekilde destekleniyor gibi görünüyor , ancak komut dosyaları bozuk ve muhtemelen DOMContentLoaded'dan önce Tamam olmalı.


1

Bu Boolean özniteliği, tarayıcıya komut dosyasının belge ayrıştırıldıktan sonra yürütülmesi gerektiğini gösterecek şekilde ayarlanmıştır. Bu özellik henüz tüm diğer büyük tarayıcılar tarafından uygulanmadığından, yazarlar komut dosyasının yürütülmesinin gerçekten erteleneceğini varsaymamalıdır. Bir erteleme komut dosyasından asla document.write () öğesini çağırmayın (Gecko 1.9.2'den beri bu, belgeyi havaya uçuracaktır). Erteleme özniteliği src özniteliğine sahip olmayan komut dosyalarında kullanılmamalıdır. Gecko 1.9.2'den beri, erc özniteliği src özniteliğine sahip olmayan komut dosyalarında yoksayılır. Bununla birlikte, Gecko 1.9.1'de erteleme özelliği ayarlanmışsa satır içi komut dosyaları bile ertelenir.

defer , krom, firefox, yani> 7 ve Safari ile çalışır

ref: https://developer.mozilla.org/en-US/docs/HTML/Element/script


0

Erteleme özniteliği bir boole özniteliğidir.

Var olduğunda, komut dosyası sayfanın ayrıştırma bittiğinde yürütüleceğini belirtir.

Not: erteleme özelliği yalnızca harici komut dosyaları içindir (yalnızca src özelliği varsa kullanılmalıdır).

Not: Harici bir komut dosyasının yürütülmesinin birkaç yolu vardır:

Eşzamansız varsa: Komut dosyası sayfanın geri kalanıyla eşzamansız olarak yürütülür (komut dosyası, sayfa ayrıştırmaya devam ederken yürütülür) Eşzamansız yoksa ve erteleme varsa: Komut dosyası, sayfa ayrıştırmayı tamamladığında yürütülür ne zaman uyumsuz ne de erteleme mevcut değil: Tarayıcı sayfayı ayrıştırmaya devam etmeden önce komut dosyası hemen getirilir ve yürütülür

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.