Должен ли я инкапсулировать блоки функциональности в анонимных функциях JavaScript? - PullRequest
8 голосов
/ 20 сентября 2010

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

(function() {
  var aVar;
  aVar.func = function() { alert('ronk'); };
  aVar.mem = 5;
})();

Поскольку мне больше не понадобится aVar, поэтому я предполагаю, что сборщик мусора удалит aVar, когда он выйдет из области видимости. Это правильно? Или интерпретаторы достаточно умны, чтобы понять, что я больше не использую переменную и немедленно ее очищаю? Есть ли какие-либо причины, такие как стиль или удобочитаемость, которые я должен не использовать анонимными функциями таким образом?

Кроме того, если я назову функцию, как это:

var operations = function() {
  var aVar;
  aVar.func = function() { alert('ronk'); };
  aVar.mem = 5;
};
operations();

тогда operations обязательно останется, пока не выйдет за рамки? Или переводчик может сразу сказать, когда он больше не нужен?

Лучший пример

Я также хотел бы уточнить, что я не обязательно говорю о глобальном масштабе. Рассмотрим блок, который выглядит как

(function() {

  var date = new Date(); // I want to keep this around indefinitely

  // And even thought date is private, it will be accessible via this HTML node
  // to other scripts.
  document.getElementById('someNode').date = date;

  // This function is private
  function someFunction() {
    var someFuncMember;
  }

  // I can still call this because I named it. someFunction remains available.
  // It has a someFuncMember that is instantiated whenever someFunction is
  // called, but then goes out of scope and is deleted. 
  someFunction();

  // This function is anonymous, and its members should go out of scope and be
  // deleted
  (function() {
    var member;
  })(); // member is immediately deleted
  // ...and the function is also deleted, right? Because I never assigned it to a
  // variable. So for performance, this is preferrable to the someFunction
  // example as long as I don't need to call the code again.

})();

Верны ли мои предположения и выводы? Всякий раз, когда я не собираюсь повторно использовать блок, я должен не только инкапсулировать его в функцию, но и инкапсулировать в анонимную функцию, чтобы функция не имела ссылок и удалялась после вызова, верно?

Ответы [ 2 ]

4 голосов
/ 20 сентября 2010

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

Чтобы ответить на два последних вопроса: для переводчика совершенно невозможно знать, что объект больше не будет использоваться, пока есть глобально видимая ссылка на него.Все, что знает переводчик, вы можете в любой момент набрать код, который зависит от window['aVar'] или window['operation'].

По сути, запомните две вещи:

  1. Покаобъект находится вокруг, ни один из его слотов не будет волшебным образом освобожден без вашего разрешения.
  2. Переменные, объявленные в глобальном контексте, являются слотами глобального объекта (window в Javascript на стороне клиента).

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

Ваш второй пример (с внутренней анонимной функцией) может быть немного переусердствован, хотя.Я бы не стал беспокоиться о том, чтобы «помочь сборщику мусора» - GC, вероятно, все равно не будет работать в середине этой функции.Беспокойство о вещах, которые будут храниться постоянно, а не только немного дольше, чем они были бы в противном случае.Эти самовыполняющиеся анонимные функции в основном являются модулями кода, которые естественным образом связаны друг с другом, поэтому хорошее руководство - подумать, описывает ли это то, что вы делаете.

Есть причины использовать анонимные функции внутри анонимных функций,хоть.Например, в этом случае:

(function () {
  var bfa = new Array(24 * 1024*1024);
  var calculation = calculationFor(bfa);
  $('.resultShowButton').click( function () {
    var text = "Result is " + eval(calculation);
    alert(text);
  } );
})();

Это приводит к тому, что этот гигантский массив захватывается обратным вызовом click, так что он никогда не исчезает.Этого можно избежать, помещая массив в собственную функцию.

1 голос
/ 20 сентября 2010

Все, что вы добавляете в глобальную область, будет оставаться там до тех пор, пока страница не будет выгружена (если вы специально не удалите ее).

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

...