事后用JavaScript捕获一个闭包

时间:2012-03-13 20:50:26

标签: javascript closures global

我有一个第三方JavaScript应用程序,它声明了几个全局函数,并且需要为这些函数定义一些变量才能工作。我宁愿不在全局范围内定义这些变量。这是一个例子:

假设您有一个全局定义的函数foo,它打印出一个名为x的外部定义变量的值。

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

我认为x在[{1}}范围内设置值的唯一方法是foo也是全局值。我希望我错了。我真正想做的是:

x

我想我能做到:

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

但这看起来非常像(function () { var x = 'someValue'; var bar = Function(foo.toString()); bar(); }()); 。 (如果归结为此,我宁愿使用全局垃圾邮件而不是使用eval。)

有没有办法“修复”全局函数,以便它们可以引用所附的值?

3 个答案:

答案 0 :(得分:2)

window属性分配值,调用该函数,然后使用delete运算符真正删除变量。

window.foo = 'bar';
magic();
delete window.foo; // Because `foo` is defined without `var`, it can be deleted

答案 1 :(得分:1)

显而易见的解决方案是修改foo以将x作为变量。但是,假设你不能/不想这样做,我可以想到两个选择:

  • x声明为全局变量。
  • 在关闭中包装foo的声明。

第一个肯定会让foo工作,但请不要采取Rob W的方法。请记住,人们告诉你“不要混淆全局命名空间”的原因并不是因为他们担心闲置的未使用的变量(这可能是一个问题,但它不是特定于全局命名空间)。这是因为使用相同名称空间的多个函数会增加覆盖其他变量的机会。以下是您在不使用其余代码的情况下使用全局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,但我认为您在避免使用该功能方面是正确的。)

答案 2 :(得分:0)

这是

的功能参数
function foo(x) {
  console.log(x)
}

如果你想通过将函数转换为字符串并创建一个接受参数的新函数,你可能会破解它很糟糕,但这很脏,因为地狱