현재 실행중인 스크립트를로드 한 스크립트 태그를 어떻게 참조합니까?


303

현재 실행중인 자바 스크립트를로드 한 스크립트 요소를 어떻게 참조 할 수 있습니까?

상황은 다음과 같습니다. HEAD 태그 아래에 페이지에 "마스터"스크립트가 많이로드되어 있습니다.

<!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"에는 다른 스크립트를 요청시로드 할 수있는 스크립트가 있습니다. HEAD 요소가 렌더링을 완료하지 않았기 때문에 HEAD 태그를 참조하지 않고 새 스크립트를 추가해야하기 때문에 일반적인 방법은 제대로 작동하지 않습니다.

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

내가하고 싶은 것은 현재 스크립트를로드 한 스크립트 요소를 참조하여 동적으로로드 된 새로운 스크립트 태그를 DOM에 추가 할 수 있습니다.

<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
경고 : DOM이 여전히로드되는 동안 DOM을 수정하면 IE6 및 IE7에서 상처를 입을 수 있습니다 . 페이지로드 후 해당 코드를 실행하는 것이 좋습니다.
Triptych

6
그것이 caniuse에 지금있는 것처럼 보입니다 : caniuse.com/#feat=document-currentscript
Tyler

답변:


653

현재 스크립트 요소를 얻는 방법 :

1. 사용 document.currentScript

document.currentScript<script>스크립트가 현재 처리되고 있는 요소를 반환합니다 .

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

혜택

  • 간단하고 명시 적입니다. 신뢰할 수 있습니다.
  • 스크립트 태그를 수정할 필요가 없습니다
  • 비동기 스크립트 ( defer& async) 와 함께 작동
  • 스크립트가 동적으로 삽입 된 상태에서 작동

문제

  • 구형 브라우저 및 IE에서는 작동하지 않습니다.
  • 모듈과 작동하지 않습니다 <script type="module">

2. 아이디로 스크립트를 선택

스크립트에 id 속성을 부여하면를 사용하여 id별로 쉽게 스크립트를 선택할 수 있습니다 document.getElementById().

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

혜택

  • 간단하고 명시 적입니다. 신뢰할 수 있습니다.
  • 거의 보편적으로 지원
  • 비동기 스크립트 ( defer& async) 와 함께 작동
  • 스크립트가 동적으로 삽입 된 상태에서 작동

문제

  • 스크립트 태그에 맞춤 속성을 추가해야합니다.
  • id 일부 브라우저의 경우 일부 브라우저에서 속성이 이상한 동작을 일으킬 수 있음

3. data-*속성을 사용하여 스크립트를 선택하십시오

스크립트에 data-*속성을 부여하면 내부에서 쉽게 선택할 수 있습니다.

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

이전 옵션보다 이점이 거의 없습니다.

혜택

  • 간단하고 명시 적입니다.
  • 비동기 스크립트 ( defer& async) 와 함께 작동
  • 스크립트가 동적으로 삽입 된 상태에서 작동

문제

  • 스크립트 태그에 맞춤 속성을 추가해야합니다.
  • querySelector()모든 브라우저에서 호환되지 않는 HTML5
  • id속성을 사용하는 것보다 덜 널리 지원
  • 주위에 얻을 것이다 <script>으로 id가장자리의 경우.
  • 다른 요소가 페이지에서 동일한 데이터 속성 및 값을 갖는 경우 혼동 될 수 있습니다.

4. src로 스크립트를 선택하십시오

데이터 속성을 사용하는 대신 선택기를 사용하여 소스별로 스크립트를 선택할 수 있습니다.

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

embed.js에서 :

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

혜택

  • 신뢰성
  • 비동기 스크립트 ( defer& async) 와 함께 작동
  • 스크립트가 동적으로 삽입 된 상태에서 작동
  • 맞춤 속성이나 ID가 필요하지 않습니다

문제

  • 않습니다 하지 로컬 스크립트에 대한 작업
  • 개발 및 생산과 같은 다른 환경에서 문제를 일으킬 것
  • 정적이고 깨지기 쉬운. 스크립트 파일의 위치를 ​​변경하려면 스크립트를 수정해야합니다
  • id속성을 사용하는 것보다 덜 널리 지원
  • 동일한 스크립트를 두 번로드하면 문제가 발생합니다

5. 모든 스크립트를 반복하여 원하는 스크립트를 찾으십시오.

또한 모든 스크립트 요소를 반복하고 각각 개별적으로 검사하여 원하는 것을 선택할 수 있습니다.

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

이를 통해 querySelector()속성을 잘 지원하지 않는 이전 브라우저에서 이전 기술을 모두 사용할 수 있습니다 . 예를 들면 다음과 같습니다.

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

이것은 어떤 접근 방식의 이점과 문제를 물려 받지만 의존하지는 않지만 querySelector()이전 브라우저에서 작동합니다.

6. 마지막으로 실행 된 스크립트를 가져옵니다

스크립트는 순차적으로 실행되므로 마지막 스크립트 요소는 현재 현재 실행중인 스크립트 인 경우가 많습니다.

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

혜택

  • 단순한.
  • 거의 보편적으로 지원
  • 맞춤 속성이나 ID가 필요하지 않습니다

문제

  • 않습니다 하지 비동기 스크립트 작업 ( defer& async)
  • 않습니다 하지 동적으로 삽입 된 스크립트 작업

4
이것이 답이되어야합니다.
Royi Namir

1
@RoyiNamir에 동의하십시오. 이것이 가장 좋은 대답입니다.
한스

27
고마워,하지만 당신은 내가 네 대답을 알고 허용 대답 한 후, 바로 :)
브라이스를

5
"document.currentScript"는 동적으로로드 된 스크립트에서 작동하지 않으며 최신 크롬 / 파이어 폭스에서 null을 반환합니다. "마지막으로 실행 된 스크립트"가 작동합니다
xwild

1
작동하지 않을 때 scriptA의 인 template섀도 DOM에 삽입
하지 supersharp

86

스크립트는 순차적으로 실행되므로 현재 실행중인 스크립트 태그는 그 때까지 페이지에서 항상 마지막 스크립트 태그입니다. 따라서 스크립트 태그를 얻으려면 다음을 수행하십시오.

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

3
이것은 간단하고 우아합니다. 자바 스크립트의 압축을 풀면 새로운 Google Charts / Visualizations API에 예제가 있습니다. 그들은 스크립트 태그 내에서 JSON 데이터를로드, 참조 : ajax.googleapis.com/ajax/static/modules/gviz/1.0/chart.js
제이슨 채찍질

1
이것은 좋은 생각이며 일반적으로 저에게 효과적입니다. 그러나 다른 스크립트에 대한 참조를 반환하는 경우가 있음을 추가해야합니다. 이유를 모르겠습니다.이를 추적 할 수 없었습니다. 결과적으로 나는 보통 다른 방법을 사용합니다. 예를 들어 스크립트 파일의 이름을 하드 코딩하고 해당 파일 이름으로 스크립트 태그를 찾습니다.
Ken Smith

53
이것이 잘못된 결과를 반환 할 수있는 곳을 생각할 수있는 한 가지 예는 스크립트 태그가 DOM에 비동기 적으로 추가되는 경우입니다.
커피 물린

9
예, 예기치 않은 결과가 발생할 수 있으므로 대신 선택기를 사용하십시오. $ ( 'script [src * = "/ mysource.js"]') ???
Jason Sebring

7
페이지를로드 한 후 스크립트를로드하면 작동하지 않습니다. 아마도 올바른 태그를 얻지 못할 것입니다.
ThemeZ

11

아마도 가장 쉬운 방법은 스크립 태그에 id속성 을 부여하는 것입니다.


2
비록 당신이 옳지 만 OP의 질문이 유효한 경우가 많이 있습니다. 1) 크롤링 할 때 2) 고객의 DOM으로 작업 할 때 그는 변하지 않을 것입니다
nichochar

10

스크립트는 "지연"또는 "비동기"속성이없는 경우에만 순차적으로 실행됩니다. 스크립트 태그의 가능한 ID / SRC / TITLE 속성 중 하나를 아는 경우에도 작동 할 수 있습니다. 따라서 Greg와 Justin의 제안은 모두 맞습니다.

document.currentScriptWHATWG 목록에 대한 제안이 이미 있습니다 .

편집 : Firefox> 4는 이미이 매우 유용한 속성을 구현하지만 IE11에서는 사용할 수 없으며 마지막으로 확인했으며 Chrome 29 및 Safari 8에서만 사용할 수 있습니다.

편집 : 아무도 "document.scripts"컬렉션을 언급하지 않았지만 다음은 현재 실행중인 스크립트를 얻는 데 좋은 크로스 브라우저 대안 일 수 있다고 생각합니다.

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

1
document.script가 아닌 document.scripts
Moritz

9

다음은 폴리 필이있는 document.CurrentScript경우 활용 하고 ID로 스크립트를 찾는 것입니다.

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

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

모든 스크립트 태그의 맨 위에 이것을 포함하면 어떤 스크립트 태그가 실행되고 있는지 지속적으로 알 수 있으며 비동기 콜백의 맥락에서 스크립트 태그를 참조 할 수 있다고 생각합니다.

테스트를 거치지 않았으므로 다른 사람에게 피드백을 남겨주세요.


id속성은 유효하지 않은 A의 script생각 요소입니다. 이 접근법은 어떤 종류의 문제를 일으킬 수 있습니까?
NR

1
@nr-아니오, 모든 요소는 id속성을 가질 수 있습니다 . id, classslot은 HTML 수준이 아닌 DOM 수준에서 정의됩니다. HTML전역 속성으로 이동하여 목록을지나 스크롤하면 "DOM 표준은 네임 스페이스의 모든 요소에 대한 클래스, ID 및 슬롯 속성에 대한 사용자 에이전트 요구 사항을 정의합니다." 이어 "클래스, ID 및 슬롯 속성은 모든 HTML 요소에 지정할 수 있습니다." DOM 사양은 여기에서 다룹니다 .
TJ Crowder 2016 년

6

페이지로드 및 스크립트 태그가 자바 스크립트 (예 : 아약스)로 추가 될 때 작동해야합니다.

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

3

현재 실행중인 스크립트 블록에 대한 참조를 얻으려면 다음 간단한 단계를 수행하십시오.

  1. 스크립트 블록 내에 임의의 고유 한 문자열을 넣습니다 (각 스크립트 블록마다 고유해야 함)
  2. document.getElementsByTagName ( 'script')의 결과를 반복하여 각 컨텐츠 (innerText / textContent 특성에서 확보)에서 고유 한 문자열을 찾습니다.

예 (ABCDE345678은 고유 ID) :

<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의 경우, 다른 스크립트를 포함하기 위해 구식 document.write () 메서드를 사용하면됩니다. DOM이 아직 렌더링되지 않았다고 언급했듯이 브라우저는 항상 선형 순서로 스크립트를 실행한다는 사실을 활용할 수 있습니다 (나중에 렌더링 될 지연 스크립트는 제외). 나머지 문서는 여전히 "존재하지 않습니다". document.write ()를 통해 작성한 것은 호출자 스크립트 바로 뒤에 배치됩니다.

원본 HTML 페이지의 예 :

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

script.js의 내용 :

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

렌더링 된 후 DOM 구조는 다음과 같습니다.

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

이것은 외부 스크립트가 아닌 인라인 스크립트에서만 작동하는 것으로 보입니다. 후자의 경우 모든 속성 innerText, text 및 textContent가 비어 있습니다.
Jos de Jong

3

비동기 및 지연된 스크립트를 처리하는 방법은 모든 스크립트 태그에 대해 onload 핸들러를 설정하고 모든 스크립트 태그에 대해 onload 핸들러를 설정하는 것입니다.

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

현재 스크립트를로드 한 스크립트를 사용하려면

var thisScript = document.currentScript;

스크립트 시작시 참조를 유지해야하므로 나중에 전화 할 수 있습니다

var url = thisScript.src

2

이 알고리즘을 고려하십시오. 스크립트가로드되면 (동일한 스크립트가 여러 개있는 경우) document.scripts를 살펴보고 올바른 "src"속성이있는 첫 번째 스크립트를 찾아서 저장 한 후 데이터 속성 또는 고유 한 className으로 '방문'으로 표시하십시오.

다음 스크립트가로드되면 document.scripts를 다시 스캔하여 이미 방문한 것으로 표시된 모든 스크립트를 전달합니다. 해당 스크립트의 첫 번째 방문하지 않은 인스턴스를 가져옵니다.

이것은 동일한 스크립트가 헤드에서 바디로, 위에서 아래로, 동기에서 비동기로로드되는 순서대로 실행될 것이라고 가정합니다.

(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;
  }
})();

특수 속성으로 표시되지 않은 일치하는 첫 번째 스크립트가 있는지 모든 스크립트를 검색합니다.

그런 다음 해당 노드가 발견되면 데이터 속성으로 표시하여 후속 스캔에서 선택하지 않도록하십시오. 이는 노드가 '방문'으로 표시되어 재 방문을 방지 할 수있는 그래프 순회 BFS 및 DFS 알고리즘과 유사합니다.


스택 오버플로에 오신 것을 환영합니다. 알고리즘에 코드를 포함 하시겠습니까?
Gary99

당신은 간다, @ Gary99
LSOJ

0

나는 이것을 FF3, IE6 & 7에서 작동하고 있습니다. 주문형로드 스크립트의 메소드는 페이지로드가 완료 될 때까지 사용할 수 없지만 여전히 유용합니다.

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

스크립트의 파일 이름을 가정하면 찾을 수 있습니다. 지금까지 Firefox에서 다음 기능 만 실제로 테스트했습니다.

  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
매우 구식입니다. 간단한 oneliner 인 querySelector를 사용하면됩니다.
Fabian von Ellerts 11

-1

다음 코드가 가장 일관되고 성능이 뛰어나고 간단한 것으로 나타났습니다.

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);
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.