Захват замыкания в JavaScript в постфактум - PullRequest
0 голосов
/ 14 марта 2012

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

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

function foo() {
    console.log(x);
}

Я думаю, что единственный способдля x значение в foo, если x также является глобальным.Надеюсь я ошибаюсь.Что я действительно хотел бы сделать, это:

(function () {
    var x = 'someValue';
    var bar = magicallyFixSoXIsntGlobal(foo);
    bar();
}());

Я думаю, я мог бы сделать:

(function () {
    var x = 'someValue';
    var bar = Function(foo.toString());
    bar();
}());

Но это похоже на eval.(Если это сводится к тому, что я предпочел бы иметь глобальный спам, чем использовать eval.)

Есть ли способ «исправить» глобальные функции, чтобы они могли ссылаться на вложенные значения?

Ответы [ 3 ]

2 голосов
/ 14 марта 2012

Присвойте значение свойству window, вызовите функцию, а затем используйте оператор delete, чтобы действительно удалить переменную.

window.foo = 'bar';
magic();
delete window.foo; // Because `foo` is defined without `var`, it can be deleted
1 голос
/ 14 марта 2012

Очевидное решение состоит в том, чтобы изменить foo, чтобы принять x в качестве переменной.Но, предполагая, что вы не можете / не хотите этого делать, я могу представить два варианта:

  • объявить x глобальной переменной.
  • Обтекание foo объявление в закрытии.

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

!function(x, exists) {
  window.x=10;
  foo();

  if(exists)
    window.x=x;
  else
    delete window.x;
}(window.x, 'x' in window);

Второй вариант не должен быть слишком сложным, если foo в настоящее время является просто объявлением function в вашемкод.В этом случае измените его на:

!function() {
  var x=10;
  function foo() {
    [...]
  }
  // foo can only be called within this block
}();

Или, если foo должен быть глобальным, но вы все равно не хотите, чтобы x был глобальным:

!function() {
  var x=10;
  window.foo=function() {
    [...]
  };
  // now foo can be called anywhere, and will still use the x declared above
}();

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

0 голосов
/ 14 марта 2012

Это параметры функции для

function foo(x) {
  console.log(x)
}

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

...