JavaScript - Làm cách nào để gọi URL của tập lệnh?


81

Tôi bao gồm myscript.js trong tệp http://site1.com/index.htmlnhư sau:

<script src=http://site2.com/myscript.js></script>

Bên trong "myscript.js", tôi muốn truy cập vào URL " http://site2.com/myscript.js ". Tôi muốn có một cái gì đó như thế này:

function getScriptURL() {
    // something here
    return s
}

alert(getScriptURL());

Nó sẽ cảnh báo " http://site2.com/myscript.js " nếu được gọi từ index.html được đề cập ở trên.




Dựa trên các URL mẫu của mình, bạn có thể muốn lưu ý hành vi mà bạn đang mong đợi nếu trình duyệt được đặt để chặn các tập lệnh của bên thứ ba.

Câu trả lời:


58

Từ http://feather.elektrum.org/book/src.html :

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

Biến myScriptbây giờ có phần tử dom script. Bạn có thể lấy url src bằng cách sử dụng myScript.src.

Lưu ý rằng điều này cần phải thực hiện như một phần của đánh giá ban đầu của tập lệnh. Nếu bạn muốn không làm ô nhiễm không gian tên Javascript, bạn có thể làm điều gì đó như:

var getScriptURL = (function() {
    var scripts = document.getElementsByTagName('script');
    var index = scripts.length - 1;
    var myScript = scripts[index];
    return function() { return myScript.src; };
})();

23
Tuy nhiên, điều này sẽ luôn trả về URL của tập lệnh phù hợp, trong tất cả các trình duyệt? Điều này có vẻ như nó sẽ trả về thẻ script cuối cùng, nhưng điều gì sẽ xảy ra nếu tài liệu có nhiều hơn một thẻ script trong đó?
MikeC 8

3
Được rồi ... câu hỏi của tôi sau đó trở thành, có phải tất cả các trình duyệt luôn tải hoàn toàn việc thực thi nội dung hoàn chỉnh của tập lệnh từ xa trước khi chuyển sang thẻ tập lệnh tiếp theo không? Điều này được tiêu chuẩn hóa nghiêm ngặt như thế nào? Tôi có thể tưởng tượng nó xảy ra song song ...
MikeC8

1
Yêu cầu các tập lệnh chạy hoàn toàn và theo thứ tự vì điều gì sẽ xảy ra nếu thẻ tập lệnh chứa document.write. Đây là lý do cho các khuyến nghị đặt tập lệnh ở cuối trang vì chúng thực sự sẽ chặn nội dung khác tải. Điều đó nói rằng, HTML5 Sửa rằng với việc sử dụng các async và hoãn các thuộc tính: whatwg.org/specs/web-apps/current-work/multipage/...
lambacck

9
Điều này không hoạt động nếu bạn tải tập lệnh sau khi trang đã tải bằng cách sử dụng thứ gì đó như sau: document.getElementsByTagName("head")[0].appendChild(scriptElement);
Seanonymous

16
Tôi đã gặp một trường hợp mà thuật toán này không hoạt động đáng tin cậy. Các thẻ tập lệnh khác được đặt thành không đồng bộ có thể chạy giữa tập lệnh của bạn được yêu cầu và chạy. Các tập lệnh này có thể thêm các tập lệnh khác vào DOM xuất hiện sau các tập lệnh của bạn. Khi tập lệnh của bạn chạy, tập lệnh cuối cùng trên trang không còn là của bạn và srctrả lại sai .
Karl

54

Bạn có thể thêm thuộc tính id vào thẻ script của mình (ngay cả khi nó nằm trong thẻ head):

<script id="myscripttag" src="http://site2.com/myscript.js"></script>

và sau đó truy cập vào src của nó như sau:

document.getElementById("myscripttag").src

tất nhiên giá trị id phải giống nhau cho mọi tài liệu bao gồm tập lệnh của bạn, nhưng tôi không nghĩ đó là một sự bất tiện lớn cho bạn.


1
Câu trả lời này phải được đánh dấu là "được chấp nhận" vì nó bao gồm các trường hợp khi bạn gọi phương thức không phải trong ngữ cảnh tập lệnh "chung" hoặc trong tập lệnh "không đồng bộ" và nó không phụ thuộc vào việc triển khai trình duyệt.
Sergei Kovalenko

Lưu ý rằng .srccó thể trả về một đường dẫn tuyệt đối, ngay cả khi một đường dẫn tương đối đã được chỉ định. Bạn có thể sử dụng.getAttribute('src')
Илья Зеленько


18

Tôi đã viết một lớp để tìm đường dẫn các tập lệnh hoạt động với các thẻ tập lệnh tải chậm và không đồng bộ.

Tôi đã có một số tệp mẫu liên quan đến các tập lệnh của mình, vì vậy thay vì viết mã cứng, tôi đã tạo lớp để tạo các đường dẫn tự động. Nguồn đầy đủ ở đây trên github.

Một thời gian trước, tôi đã sử dụng arg.callee để thử và làm điều gì đó tương tự nhưng gần đây tôi đã đọc trên MDN rằng nó không được phép ở chế độ nghiêm ngặt .

function ScriptPath() {
  var scriptPath = '';
  try {
    //Throw an error to generate a stack trace
    throw new Error();
  }
  catch(e) {
    //Split the stack trace into each line
    var stackLines = e.stack.split('\n');
    var callerIndex = 0;
    //Now walk though each line until we find a path reference
    for(var i in stackLines){
      if(!stackLines[i].match(/http[s]?:\/\//)) continue;
      //We skipped all the lines with out an http so we now have a script reference
      //This one is the class constructor, the next is the getScriptPath() call
      //The one after that is the user code requesting the path info (so offset by 2)
      callerIndex = Number(i) + 2;
      break;
    }
    //Now parse the string for each section we want to return
    pathParts = stackLines[callerIndex].match(/((http[s]?:\/\/.+\/)([^\/]+\.js)):/);
  }

  this.fullPath = function() {
    return pathParts[1];
  };

  this.path = function() {
    return pathParts[2];
  };

  this.file = function() {
    return pathParts[3];
  };

  this.fileNoExt = function() {
    var parts = this.file().split('.');
    parts.length = parts.length != 1 ? parts.length - 1 : 1;
    return parts.join('.');
  };
}

1
Đến bữa tiệc ở đây hơi muộn, nhưng tôi đã thử đoạn mã này và nhận thấy rằng phần mà nó thêm 2 vào chỉ mục hiện tại trong vòng lặp for "callerIndex = Number (i) + 2;" dường như phá vỡ là không cần thiết và khiến nó không hoạt động. Chỉ cần loại bỏ "+ 2" là nó hoạt động. Có điều gì đó tôi đang hiểu sai hoặc một số tình huống khác mà + 2 sẽ cần thiết?
Scott Smith

2
bạn không cần phải ném "Error" theo cách này (để lấy nó là ".stack") nó chỉ là một đối tượng giống như các đối tượng khác: console.log (new Error (). stack);
Abdullah

1
Cảm ơn ý tưởng này và cảm ơn @ AbdullahAydın về ý tưởng ngăn chặn ném. Sau đó, tôi đoán một lớp lót sau đây sẽ thực hiện thủ thuật, phải không? var scriptUrl = new Error (). stack.match (/ @ (https?: \ / \ /.+): \ d +: \ d + /) [1]
Pierre-Antoine

1
Ngoài ra @ Pierre-Antoine hãy nhớ rằng thuộc tính Error.prototype.stack là không chuẩn: / bạn nên sử dụng nó một cách cẩn thận. developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Abdullah

3
@ AbdullahAydın: Lưu ý rằng thuộc tính ngăn xếp của một lỗi mới không được phổ biến trong trình duyệt IE và Edge cho đến khi lỗi được đưa ra.
Bob Arlof

15

nếu bạn có cơ hội sử dụng jQuery, mã sẽ giống như sau:

$('script[src$="/myscript.js"]').attr('src');

Nó có hoạt động với các tập lệnh tải chậm, không đồng bộ và lười biếng không?
Stephan

Nó chỉ là xem qua DOM để tìm thẻ script với src "/myscript.js". các thuộc tính khác sẽ không thành vấn đề
Rebs

Để sử dụng điều này với wordpress ở bất kỳ nơi nào khác gắn phiên bản, bạn nên sử dụng $ ('script [src * = "/ myscript.js"]'). Attr ('src'); theo cách này nó sẽ bỏ qua? ver = 2.3.3 ở cuối tập lệnh. Dấu * sẽ giữ cho nó hoạt động bất kể những gì ở cuối.
Mav2287

15

Giải pháp đơn giản và dễ hiểu hoạt động rất tốt:

Nếu không phải IE, bạn có thể sử dụng document.currentScript
Đối với IE, bạn có thể làm document.querySelector('script[src*="myscript.js"]')
như vậy:

function getScriptURL(){
 var script =  document.currentScript || document.querySelector('script[src*="myscript.js"]')
 return script.src
}

2

Mã sau cho phép bạn tìm phần tử tập lệnh với tên đã cho

var scripts = document.getElementsByTagName( 'script' );
        var len = scripts.length
        for(var i =0; i < len; i++) {
            if(scripts[i].src.search("<your JS file name") > 0 && scripts[i].src.lastIndexOf("/") >= 0) {
                absoluteAddr = scripts[i].src.substring(0, scripts[i].src.lastIndexOf("/") + 1);
                break;
            }
        }

-6

Bạn không thể sử dụng location.href hoặc location.host và sau đó thêm tên script?


1
Điều đó sẽ không hoạt động, bởi vì tập lệnh đang chạy trong trang site1.com/index.html . Vì vậy, ngay cả khi tập lệnh được tải từ site2.com, nếu bạn truy cập vị trí từ bên trong tập lệnh, nó sẽ trả về " site1.com/index.html " ...
MikeC8
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.