Yürütülmekte olan komut dosyasını yükleyen komut dosyası etiketine nasıl başvurabilirim?


305

Çalışmakta olan javascript'i yükleyen kod öğesine nasıl başvurabilirim?

Durum şu. HEAD etiketi altında ilk şey, sayfada yüksek yüklenen bir "ana" komut dosyası var.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<script type="text/javascript" src="scripts.js"></script>

"Scripts.js" dosyasında, diğer komut dosyalarının istek üzerine yüklenebilmesi gereken bir komut dosyası vardır. HEAD öğesi oluşturmayı bitirmediğinden, HEAD etiketine başvurmadan yeni komut dosyaları eklemem gerektiğinden normal yöntem benim için pek işe yaramıyor:

document.getElementsByTagName('head')[0].appendChild(v);

Ne yapmak istiyorum, daha sonra yeni dinamik olarak yüklenmiş komut dosyası etiketlerimi daha sonra DOM içine ekleyebilirsiniz böylece geçerli komut dosyası yüklenen komut öğesi referanstır.

<script type="text/javascript" src="scripts.js"></script>
loaded by scripts.js--><script type="text/javascript" src="new_script1.js"></script>
loaded by scripts.js --><script type="text/javascript" src="new_script2.js"></script>

1
Uyarı kelimesi: DOM'u yükleme sırasında değiştirmek, IE6 ve IE7'de size zarar veren bir dünyaya neden olacaktır . Sayfa yüklendikten sonra bu kodu çalıştırmanız daha iyi olur.
Triptik

6
Şu anda caniuse'da gibi görünüyor: caniuse.com/#feat=document-currentscript
Tyler

Yanıtlar:


654

Geçerli komut dosyası öğesinin edinilmesi:

1. Kullanım document.currentScript

document.currentScript<script>betiği şu anda işlenen öğeyi döndürür .

<script>
var me = document.currentScript;
</script>

Yararları

  • Basit ve açık. Dürüst.
  • Komut dosyası etiketini değiştirmenize gerek yok
  • Eşzamansız komut dosyalarıyla çalışır ( defer& async)
  • Dinamik olarak eklenen komut dosyalarıyla çalışır

sorunlar

  • Eski tarayıcılarda ve IE'de çalışmaz.
  • Modüller ile çalışmaz <script type="module">

2. Komut dosyasını kimliğe göre seçin

Komut dosyasına bir id niteliği vermek, onu kullanarak içeriden kimliğe göre kolayca seçmenizi sağlar document.getElementById().

<script id="myscript">
var me = document.getElementById('myscript');
</script>

Yararları

  • Basit ve açık. Dürüst.
  • Neredeyse evrensel olarak destekleniyor
  • Eşzamansız komut dosyalarıyla çalışır ( defer& async)
  • Dinamik olarak eklenen komut dosyalarıyla çalışır

sorunlar

  • Komut dosyası etiketine özel bir özellik eklenmesini gerektirir
  • id özniteliği bazı kenar durumlarda bazı tarayıcılarda komut dosyaları için garip davranışlara neden olabilir

3. Bir data-*nitelik kullanarak komut dosyasını seçin

Komut dosyasına bir data-*öznitelik vermek, içinden özniteliği kolayca seçmenizi sağlar.

<script data-name="myscript">
var me = document.querySelector('script[data-name="myscript"]');
</script>

Bu, önceki seçeneğe göre çok az fayda sağlar.

Yararları

  • Basit ve açık.
  • Eşzamansız komut dosyalarıyla çalışır ( defer& async)
  • Dinamik olarak eklenen komut dosyalarıyla çalışır

sorunlar

  • Komut dosyası etiketine özel bir özellik eklenmesini gerektirir
  • HTML5 ve querySelector()tüm tarayıcılarda uyumlu değil
  • idÖzelliği kullanmaktan daha az desteklenir
  • Kenar kasaları <script>ile dolaşacak id.
  • Başka bir öğenin sayfada aynı veri özniteliğine ve değere sahip olması durumunda kafası karışabilir.

4. src'ye göre komut dosyasını seçin

Veri özniteliklerini kullanmak yerine, komut dosyasını kaynağa göre seçmek için seçiciyi kullanabilirsiniz:

<script src="//example.com/embed.js"></script>

Embed.js'de:

var me = document.querySelector('script[src="//example.com/embed.js"]');

Yararları

  • Dürüst
  • Eşzamansız komut dosyalarıyla çalışır ( defer& async)
  • Dinamik olarak eklenen komut dosyalarıyla çalışır
  • Özel özellik veya kimlik gerekmez

sorunlar

  • Does not yerel komut için çalışmak
  • Geliştirme ve Üretim gibi farklı ortamlarda sorunlara neden olur
  • Statik ve kırılgan. Komut dosyasının yerini değiştirmek için komut dosyasının değiştirilmesi gerekir
  • idÖzelliği kullanmaktan daha az desteklenir
  • Aynı komut dosyasını iki kez yüklerseniz sorunlara neden olur

5. İstediğinizi bulmak için tüm komut dosyalarının üzerine gelin

Ayrıca, her komut dosyası öğesinin üzerinde döngü yapabilir ve istediğimiz öğeyi seçmek için her birini ayrı ayrı kontrol edebiliriz:

<script>
var me = null;
var scripts = document.getElementsByTagName("script")
for (var i = 0; i < scripts.length; ++i) {
    if( isMe(scripts[i])){
      me = scripts[i];
    }
}
</script>

Bu, önceki tekniklerin her ikisini querySelector()de öznitelikleri iyi desteklemeyen eski tarayıcılarda kullanmamızı sağlar . Örneğin:

function isMe(scriptElem){
    return scriptElem.getAttribute('src') === "//example.com/embed.js";
}

Bu, hangi yaklaşımın kullanıldığının yararlarını ve sorunlarını devralır, ancak buna güvenmez, querySelector()bu nedenle eski tarayıcılarda çalışır.

6. Son çalıştırılan komut dosyasını alın

Komut dosyaları sırayla yürütüldüğünden, son komut dosyası öğesi şu anda çalışan komut dosyası olur:

<script>
var scripts = document.getElementsByTagName( 'script' );
var me = scripts[ scripts.length - 1 ];
</script>

Yararları

  • Basit.
  • Neredeyse evrensel olarak destekleniyor
  • Özel özellik veya kimlik gerekmez

sorunlar

  • Does not asenkron komut ile çalışmak ( defer& async)
  • Does not dinamik olarak eklenmesini komut dosyaları ile çalışmak

4
Cevap bu olmalı.
Royi Namir

1
@RoyiNamir ile aynı fikirde. Bu en iyi cevap.
Hans

27
Teşekkürler çocuklar, ama kabul edilen cevaptan 4 yıl sonra cevap verdiğimi biliyorsunuz , doğru :)
brice

5
"document.currentScript" benim için dinamik yüklü komut dosyalarıyla çalışmaz, en son chrome / firefox'ta null
değerini

1
çalışmadığında scriptbir olduğunu templatebir gölge DOM takılı
Supersharp

86

Komut dosyaları sırayla yürütüldüğünden, şu anda yürütülen komut dosyası etiketi her zaman o zamana kadar sayfadaki son komut dosyası etiketidir. Yani, komut dosyası etiketini almak için şunları yapabilirsiniz:

var scripts = document.getElementsByTagName( 'script' );
var thisScriptTag = scripts[ scripts.length - 1 ];

3
Bu basit ve zariftir. Javascript'i paketinden çıkarırsanız, yeni Google Grafikler / Görselleştirmeler API'sında bunun bir örneği vardır. JSON verilerini komut dosyası etiketinden yüklerler, bkz: ajax.googleapis.com/ajax/static/modules/gviz/1.0/chart.js
Jason Thrasher

1
Bu harika bir fikir ve normalde benim için çalışıyor. Ama eklemeliyim ki, farklı bir senaryoya bir referans döndürdüğüm zamanlar var. Neden olduğundan emin değilim - bunu takip edemedik. Sonuç olarak, genellikle farklı bir yöntemle gidiyorum, örneğin, komut dosyasının adını sabit kodluyorum ve bu dosya adıyla komut dosyası etiketini arıyorum.
Ken Smith

53
Bunun yanlış sonuçlar verebileceği bir yer olduğunu düşünebileceğim bir örnek, DOM'a eşzamansız olarak bir komut dosyası etiketi eklendiğinde.
Coffee Bite

9
Evet bunun öngörülemeyen sonuçları olabilir, bunun yerine bir seçici kullanmayı deneyebilirsiniz: $ ('script [src * = "/ mysource.js"]') ???
Jason Sebring

7
Sayfa yüklendikten sonra komut dosyalarınız yüklendiğinde çalışmaz. Muhtemelen doğru etiketi alamazsınız.
ThemeZ

11

Muhtemelen yapılacak en kolay şey, komut dosyası etiketinize bir idözellik vermek olacaktır .


2
Haklı olmanıza rağmen, OP'nin sorusunun geçerli olduğu birçok durum var, bir çift şöyle olacak: 1) tararken 2) bir müşterinin DOM'si ile çalışırken ve değiştirmek istemiyorsa
nichochar

10

Komut dosyası, yalnızca "erteleme" veya "eşzamansız" öznitelikleri yoksa sırayla yürütülür. Komut dosyası etiketinin olası ID / SRC / TITLE özelliklerinden birini bilmek bu durumlarda da işe yarayabilir. Dolayısıyla hem Greg hem de Justin önerileri doğrudur.

document.currentScriptWHATWG listelerinde zaten bir teklif var .

DÜZENLEME : Firefox> 4 zaten bu çok kullanışlı özelliği uyguluyor ancak son kontrol ettiğim IE11'de mevcut değil ve sadece Chrome 29 ve Safari 8'de mevcut.

DÜZENLEME : Kimse "document.scripts" koleksiyonundan bahsetmedi, ancak şu anda çalışan komut dosyasını almak için iyi bir çapraz tarayıcı alternatifi olabileceğine inanıyorum:

var me = document.scripts[document.scripts.length -1];

1
Bu document.scripts değil document.script
Moritz

9

Burada, document.CurrentScriptvarsa koddan yararlanarak betiği kimliğe göre bulmaya geri dönen bir çok dolgu var.

<script id="uniqueScriptId">
    (function () {
        var thisScript = document.CurrentScript || document.getElementByID('uniqueScriptId');

        // your code referencing thisScript here
    ());
</script>

Bunu her komut dosyası etiketinin üstüne eklerseniz, hangi komut dosyası etiketinin tetiklendiğini sürekli olarak bileceğinizi ve ayrıca eşzamansız geri arama bağlamında komut dosyası etiketine başvurabileceğinizi düşünüyorum.

Test edilmediğinden, denerseniz başkaları için geri bildirim bırakın.


idNiteliktir geçersiz bir de scriptolsa eleman. Bu yaklaşım ne tür problemler yaratabilir?
nr

1
@nr - Hayır, tüm öğelerin bir idözelliği olabilir. id,, classve slotHTML düzeyinde değil DOM düzeyinde tanımlanır. HTML'deki global niteliklere gidip listeyi geçerseniz, "DOM standardı, herhangi bir ad alanındaki herhangi bir öğenin sınıf, kimlik ve alan özellikleri için kullanıcı aracısı gereksinimlerini tanımlar." ardından "Sınıf, kimlik ve alan özellikleri tüm HTML öğelerinde belirtilebilir." DOM spesifikasyonları bu konuyu burada ele alıyor .
TJ Crowder

6

Sayfa yüklenirken ve javascript ile bir komut dosyası eklendiğinde çalışmalıdır (ör. Ajax ile)

<script id="currentScript">
var $this = document.getElementById("currentScript");
$this.setAttribute("id","");
//...
</script>

3

Geçerli yürütme komut dosyası bloğuna başvuru almak için şu basit adımları izleyin:

  1. Komut dosyası bloğuna rastgele benzersiz bir dize koyun (her komut dosyası bloğunda benzersiz / farklı olmalıdır)
  2. İçeriğinin her birinden benzersiz bir dize (innerText / textContent özelliğinden elde edilir) bakarak document.getElementsByTagName ('script') sonucunu yineleyin.

Örnek (ABCDE345678 benzersiz kimliktir) :

<script type="text/javascript">
var A=document.getElementsByTagName('script'),i=count(A),thi$;
for(;i;thi$=A[--i])
  if((thi$.innerText||thi$.textContent).indexOf('ABCDE345678'))break;
// Now thi$ is refer to current script block
</script>

btw, davanız için eski moda document.write () yöntemini kullanarak başka bir komut dosyası kullanabilirsiniz. DOM'un henüz oluşturulmadığından bahsettiğiniz gibi, tarayıcının her zaman komut dosyasını doğrusal sırada yürütmesinden (daha sonra oluşturulacak ertelenmiş olanlar hariç) yararlanabilirsiniz, bu nedenle belgenizin geri kalanı hala "mevcut değildir". Document.write () ile yazdığınız her şey, arayan komut dosyasının hemen sonrasına yerleştirilir.

Orijinal HTML sayfası örneği :

<!doctype html>
<html><head>
<script src="script.js"></script>
<script src="otherscript.js"></script>
<body>anything</body></html>

Script.js içeriği :

document.write('<script src="inserted.js"></script>');

Oluşturulduktan sonra DOM yapısı şu şekilde olacaktır:

HEAD
  SCRIPT script.js
  SCRIPT inserted.js
  SCRIPT otherscript.js
BODY

Bu, harici komut dosyaları için değil, yalnızca satır içi komut dosyaları için işe yarar. İkinci durumda, innerText, text ve textContent öğelerinin tüm özellikleri boştur.
Jos de Jong

3

Zaman uyumsuz ve ertelenmiş komut dosyalarıyla uğraşmak için bir yaklaşım, tüm kod etiketleri için onload işleyicisini kullanarak bir onload işleyicisini kullanmaktır ve ilk yürütme işlemi sizin olmalıdır.

function getCurrentScript(callback) {
  if (document.currentScript) {
    callback(document.currentScript);
    return;
  }
  var scripts = document.scripts;
  function onLoad() {
    for (var i = 0; i < scripts.length; ++i) {
      scripts[i].removeEventListener('load', onLoad, false);
    }
    callback(event.target);
  }
  for (var i = 0; i < scripts.length; ++i) {
    scripts[i].addEventListener('load', onLoad, false);
  }
}

getCurrentScript(function(currentScript) {
  window.console.log(currentScript.src);
});

3

Şu anda kullanabileceğiniz betiği yükleyen betiği almak için

var thisScript = document.currentScript;

Komut dosyanızın başında bir referans tutmanız gerekir, böylece daha sonra arayabilirsiniz

var url = thisScript.src

2

Bu algoritmayı düşünün. Komut dosyanız yüklendiğinde (birden fazla aynı komut dosyası varsa) document.scripts dosyasına bakın, doğru "src" özniteliğine sahip ilk komut dosyasını bulun ve kaydedin ve bir data özniteliği veya benzersiz className ile 'ziyaret edildi' olarak işaretleyin.

Bir sonraki komut dosyası yüklendiğinde, zaten ziyaret edilmiş olarak işaretlenmiş herhangi bir komut dosyasını ileterek document.scripts dosyasını tekrar tarayın. Bu betiğin ilk ziyaret edilmemiş örneğini alın.

Bu, aynı komut dosyalarının büyük olasılıkla, başından gövdeye, yukarıdan aşağıya, eşzamanlıdan eşzamansız olarak yüklendikleri sırayla yürütüleceklerini varsayar.

(function () {
  var scripts = document.scripts;

  // Scan for this data-* attribute
  var dataAttr = 'data-your-attribute-here';

  var i = 0;
  var script;
  while (i < scripts.length) {
    script = scripts[i];
    if (/your_script_here\.js/i.test(script.src)
        && !script.hasAttribute(dataAttr)) {

        // A good match will break the loop before
        // script is set to null.
        break;
    }

    // If we exit the loop through a while condition failure,
    // a check for null will reveal there are no matches.
    script = null;
    ++i;
  }

  /**
   * This specific your_script_here.js script tag.
   * @type {Element|Node}
   */
  var yourScriptVariable = null;

  // Mark the script an pass it on.
  if (script) {
    script.setAttribute(dataAttr, '');
    yourScriptVariable = script;
  }
})();

Bu, özel nitelik ile işaretlenmemiş ilk eşleşen komut dosyasının tüm komut dosyasını tarar.

Ardından, bu düğümü, bulunursa, sonraki özniteliklerin seçmeyeceği bir veri özniteliğiyle işaretleyin. Bu, revisitng'i önlemek için düğümlerin 'ziyaret edildi' olarak işaretlenebildiği grafik geçişli BFS ve DFS algoritmalarına benzer.


Stack Overflow'a hoş geldiniz. Algoritmaya bazı kodlar eklemek ister misiniz?
Gary99

Ghar, @ Gary99
LSOJ

0

FF3, IE6 ve 7'de çalışan bunu aldım. İsteğe bağlı yüklü komut dosyalarındaki yöntemler, sayfa yükleme işlemi tamamlanana kadar kullanılamaz, ancak bu hala çok yararlıdır.

//handle on-demand loading of javascripts
makescript = function(url){
    var v = document.createElement('script');
    v.src=url;
    v.type='text/javascript';

    //insertAfter. Get last <script> tag in DOM
    d=document.getElementsByTagName('script')[(document.getElementsByTagName('script').length-1)];
    d.parentNode.insertBefore( v, d.nextSibling );
}

0

Komut dosyasının dosya adını varsa, bulabilirsiniz. Firefox'ta şu işlevi gerçekten test ettim.

  function findMe(tag, attr, file) {
    var tags = document.getElementsByTagName(tag);
    var r = new RegExp(file + '$');
    for (var i = 0;i < tags.length;i++) {
      if (r.exec(tags[i][attr])) {
        return tags[i][attr];
      }
    }
  };
  var element = findMe('script', 'src', 'scripts.js');

1
Çok eski. Bu basit bir oneliner querySelector ile yapılabilir!
Fabian von Ellerts

-1

Aşağıdaki kodu en tutarlı, performanslı ve basit bulduk.

var scripts = document.getElementsByTagName('script');
var thisScript = null;
var i = scripts.length;
while (i--) {
  if (scripts[i].src && (scripts[i].src.indexOf('yourscript.js') !== -1)) {
    thisScript = scripts[i];
    break;
  }
}
console.log(thisScript);
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.