Можно ли ссылаться на функцию или объект из определенного тега script в HTML файл

Представьте, что в файле HTML есть следующий код:

<script id='tag-1'>
  function foo(){
    alert("this is foo-1");
  }
</script>

<script id='tag-2'>
  function foo(){
    alert("this is foo-2");
  }
</script>

<script id='tag-3'>
  function foo(){
    alert("this is foo-3");
  }
</script>

Можно ли вызвать функцию foo из тега script с id tag-2? Мне просто интересно узнать, есть ли кросс-браузерное решение? Спасибо, ребята.


Хорошо, у нас есть два очень важных предложения - тот, который я обозначил для принятого ответа, и еще один комментарий, стоящий ниже этого сообщения - тот, который предлагает @dfsq. Спасибо всем, ребята!!!

Ответ 1

Да, это вполне возможно, но вы должны использовать другой тип, кроме text/javascript.

<script id='tag-1' type="myScriptHolder">
  function foo(){
    alert("this is foo-1");
  }
</script>

<script id='tag-2' type="myScriptHolder">
  function foo(){
    alert("this is foo-2");
  }
</script>

<script id='tag-3' type="myScriptHolder">
  function foo(){
    alert("this is foo-3");
  }
</script>

<script>
$.globalEval($('#tag-1').text();
</script>

Ответ 2

Нет, это невозможно, не прибегая к eval().

Как только каждый блок script оценивается браузером, предыдущие версии функции перезаписываются.

Вы можете получить доступ к текстовому контексту каждого тега <script>, но только в том случае, если он встроен. Для доступа к тегу <script src="..."> требуется AJAX.

Ответ 3

Нет, это невозможно. Все Javascript-коды в одном окне имеют одно и то же пространство имен, поэтому то, что вы делаете в своем примере, просто переопределяет foo, что означает, что в итоге у вас есть только "foo-3".

iframes имеют собственное пространство имен, но было бы бесполезно использовать iframes для чего-то вроде этого.

Если функции нужны только для их соответствующих скриптов, вы можете обернуть каждый script в функцию самоисполнения, например

(function() {
  function foo(){
    alert("this is foo-1");
  }
})();

Это означало бы, что foo будет недоступным извне, чем script, который, очевидно, может работать или не работать для вас в зависимости от того, где используется функция.

Единственной альтернативой может быть создание собственных пространств имен для функций, например:

var namespace1 = {};
namespace1.foo = function foo() {...}

Ответ 4

Javascript не имеет функции перегрузки. Каждое следующее объявление с тем же именем (переменная или функция) просто повторно объявляет его с предоставленным новым значением. Таким образом, в вашем случае функция из tag-3 будет всегда выполняться.

Возможное решение того, что вы хотите - 1. Дайте разные имена для каждой функции.
или
2. Если вы ожидаете, что функции будут вызываться по-разному в зависимости от предоставленных аргументов. Вы можете проверить объект неявных аргументов внутри функции и выполнить необходимые операции в зависимости от этого.

Простой пример второго решения можно задать следующим образом.

function foo(bar){
    if(typeof bar==="number"){
         //Do number specific stuff here
    } else if(typeof bar==="string"){
        //Do string specific stuff here
    } else {
    }
}

Ответ 5

Вы можете реализовать технику имен имен javascript, которая довольно распространена. Это создает новый объект javascript, который доступен, и вы можете ссылаться через вызовы CodeGuru.File1.Foo();

var CodeGuru = CodeGuru || {};  
var CodeGuru.File1 = CodeGuru.File1 || {};
(function(CodeGuru) {
    CodeGuru.File1.Foo = function() {
        //insert code
    }
 })(CodeGuru);

Ответ 6

Как насчет чего-то вроде этого:

if (typeof (GenLib) == "undefined") GenLib = {};

    GenLib.Tag1 = {};
    GenLib.Tag2 = {};
    GenLib.Tag3= {};

    GenLib.Tag1.Foo = function () {
        alert("this is foo-1");
    };

    GenLib.Tag2.Foo = function () {
        alert("this is foo-2");
    };

    GenLib.Tag3.Foo = function () {
        alert("this is foo-3");
    };

    var theOneYouWantNow = GenLib.Tag2; // Or Tag1 or Tag3, use if/switch/whatever here.

    theOneYouWantNow.Foo();