Вложение внешнего скрипта jQuery

У меня есть внешний файл JavaScript, который будет использоваться на страницах с множеством других скриптов. В моем сценарии много jQuery, который отслеживает события, и по замыслу у меня объявлено много глобальных переменных. Я читал статьи о лучших практиках, и много говорилось о «загрязнении глобального пространства имен» и непреднамеренном взаимодействии скриптов.

Как лучше всего заключить (инкапсулировать?) мой файл JavaScript, чтобы:

  • Я все еще могу получить доступ к некоторым переменным за пределами корпуса
  • Слушатели событий jQuery будут работать правильно

Я не вправе раскрывать код, поэтому приветствуются даже общие ответы. Кроме того, приветствуются любые другие советы о том, как сделать скрипты менее уязвимыми для других скриптов на странице.

Я нашел стили вложения для обычного JavaScript, но не усложняет ли это использование jQuery?


person Community    schedule 10.06.2011    source источник
comment
я думаю, что лучший способ - просто использовать объекты или использовать пространства имен   -  person venimus    schedule 10.06.2011


Ответы (6)


Как правило, это сводится к инкапсуляции ваших объектов в «пространство имен». Я использую здесь кавычки, потому что этот термин не является официальной семантикой в ​​JavaScript, а достигается за счет базовой инкапсуляции объектов.

Есть несколько способов сделать это, и в конечном итоге все сводится к личным предпочтениям.

Один из подходов состоит в том, чтобы просто использовать базовый объект JS и хранить в нем все. Имя объекта должно быть семантическим и придавать объекту какое-то значение, но в остальном его цель состоит в том, чтобы просто обернуть ваш собственный код и не допустить его попадания в глобальное пространство имен.

var SomeName = {
    alpha: 1,
    beta: {a: 1, b: 2},
    gamma: function(){ 
        SomeName.alpha += 1;
    }
}

В этом случае в глобальном пространстве имен находится только SomeName. Единственным недостатком этого подхода является то, что все внутри пространства имен является общедоступным, и вы должны использовать полное пространство имен для ссылки на объект, а не использовать «это», например. в SomeName.gamma мы должны использовать SomeName.alpha для ссылки на содержимое alpha.

Другой подход состоит в том, чтобы сделать ваше пространство имен функцией со свойствами. Приятной особенностью этого подхода является то, что вы можете создать «частную» переменную через замыкания. Это также дает вам доступ к закрытым функциям и переменным без полной ссылки на пространство имен.

var SomeName = (function(){
   var self = this;
   var privateVar = 1;
   var privateFunc = function() { };   

   this.publicVar = 2;
   this.publicFunc = function(){
       console.log(privateVar);
       console.log(this.publicVar); // if called via SomeName.publicFunc

       setTimeout(function(){ 
           console.log(self.publicVar);
           console.log(privateVar);
       }, 1000);
   };
}();

Еще одним преимуществом этого подхода является то, что он позволяет защитить глобальные переменные, которые вы хотите использовать. Например, если вы используете jQuery И другую библиотеку, которая создает переменную $, вы всегда можете быть уверены, что ссылаетесь на jQuery при использовании $ следующим образом:

var SomeName = (function($){
    console.log($('div'));
})(jQuery);
person Matt    schedule 10.06.2011

Один из способов заключается в таком пространстве имен:

var MyNamespace = {
    doSomething: function() {},
    reactToEvent: function() {},
    counter: 0
}

Вам просто нужно будет обратиться к функции или переменной, используя пространство имен: MyNamespace.reactToEvent. Это прекрасно работает для разделения того, что вы обычно имеете в window (где все конфронтации).

person natedavisolds    schedule 10.06.2011
comment
Это, безусловно, самый простой способ - создать свое собственное глобальное свойство, в которое вы все поместите. - person John Strickler; 10.06.2011

Вы можете обернуть свой код в анонимную функцию Javascript и вернуть только то, что хотите показать внешнему миру. Вам нужно будет добавить префикс var к вашим глобальным переменным, чтобы они оставались только в области действия анонимной функции. Что-то вроде этого:

var myStuff = (function() {

   var globalVar1;
   var globalVar2;
   var privateVar1;

   function myFunction() {
     ...
   }

   function myPrivateFunction() {
     ...
   }

   return {
      var1: globalVar1,
      var2: globalVar2,
      myFunction: myFunction
   };

})();

Теперь вы можете получить доступ к myStuff.var1 и myStuff.myFunction().

person Vivin Paliath    schedule 10.06.2011

Два способа инкапсулировать или ограничить загрязнение пространства имен

1) Создать один глобальный вар и запихнуть в него все что нужно.

var g = {};
g.somevar = "val";
g.someothervar = "val2";
g.method1 = function() 
{
   // muck with somevar
   g.somevar = "something else";
};

2) Для встроенных скриптов рассмотрите возможность ограничения объема вызываемых функций.

<script>
(  
   function(window)
   {
      // do stuff with g.somevar
      if(g.somevar=="secret base")
        g.docrazystuff();      

   }
)();  // call function(window) then allow function(window) to be GC'd as it's out of scope now
</script>
person mrk    schedule 10.06.2011

Я только начал использовать RequireJS и стал одержим им.

По сути, это система управления зависимостями в модульном формате JavaScript. Поступая таким образом, вы можете практически исключить присоединение чего-либо к глобальному пространству имен.

Что хорошо, так это то, что вы ссылаетесь только на один скрипт на своей странице require.js, а затем указываете, какой скрипт запускать первым. Отсюда и все волшебство...

Вот пример скрипта реализации:

require([
   //dependencies
   'lib/jquery-1.6.1'
], function($) {
   //You'll get access to jQuery locally rather than globally via $


});

Прочтите RequireJS API и посмотрите, подходит ли он вам. Сейчас я пишу все свои сценарии так. Это здорово, потому что в начале каждого скрипта вы точно знаете, какие у вас зависимости похожи на серверные языки — Java или C#.

person John Strickler    schedule 10.06.2011
comment
Хм, меня это очень интересует. По вашему опыту, сколько модификаций страниц (возможно, с несколькими отдельными внешними файлами скриптов, несколькими встроенными скриптами) необходимо, чтобы это заработало? Было ли это легко? - person ; 10.06.2011
comment
@chris Принятие этого было не так уж плохо, все внешние файлы сценариев используют функцию define() для регистрации их как модулей. Тогда ваша страница реализации просто ссылается на те модули, которые вы определили. Я собираюсь написать сообщение в блоге об этом, вероятно, на следующей неделе или около того. Обязательно отпишусь здесь со ссылкой. - person John Strickler; 10.06.2011

Это обычная практика с плагинами jQuery по тем же причинам, которые вы упомянули:

;(function ($) {

    /* ... your code comes here ... */

})(jQuery);

Это немедленная функция. Если вы объявите свои «глобальные» переменные внутри, они будут локальными для этого закрытия (все еще «глобальными» для кода, который вы создаете внутри). Здесь также будут работать ваши прослушиватели событий, и вы по-прежнему сможете обращаться к реальным глобальным переменным.

person aorcsik    schedule 10.06.2011
comment
Спасибо за предложение, но мне нужно иметь доступ к определенным переменным за пределами корпуса. - person ; 10.06.2011
comment
И что вас остановит в этом случае? - person aorcsik; 10.06.2011
comment
они будут локальными для этого закрытия - person ; 10.06.2011