【问题标题】:Inject variables into closure将变量注入闭包
【发布时间】:2013-07-08 02:27:32
【问题描述】:

在不将其绑定到窗口对象的情况下,实现这样的事情的正确方法是什么?

x = function(fn)
{
    foo = 'bar';
    fn();
}

x(function()
{
    console.log(foo) // error happens here
});

在 PHP 中,您可以通过“使用”指令进行操作。

$foo = 'bar';
$fn = function() use($foo)
{
    echo $foo; // bar
}

编辑:我稍微更改了这段代码。我想要实现的是,使声明的变量在闭包中可用,而无需将其传递到那里。

foo = 'bar';
console.log(foo) // bar
console.log(window.foo) // bar
console.log(this.foo) // bar

我想实现同样的效果,另外一个对象被绑定为“this”。

【问题讨论】:

  • 我没有得到你想要的。我只希望答案不是with
  • 那不应该说undefined。在这里工作正常jsbin.com/evacak/1/edit
  • 这行得通...我在控制台中得到 'bar' 和 'foo'
  • 您的新代码仍然有效(即使添加 var 会更简洁)...
  • 一旦你发现真正困扰你的事情,你可能应该关闭这个烂摊子并提出一个新问题。

标签: php javascript closures


【解决方案1】:

如果我了解您的需求,您可以这样做:

var closure_variables = new Object();;
closure_variables.foo = 'bar';
window.bar = 'foo'

(function(variables)
{
    console.log(variables.foo) // undefined
    console.log(bar) // foo
})(closure_variables)

或者你甚至可以直接在参数中传递 foo。

【讨论】:

  • 您犯的错误与其他类似(相同?)答案相同。
  • 我会提供一个重复的评论.. 这也需要(function (closure_variables)
【解决方案2】:

好吧,你猜怎么着,JavaScript 有 真正的 闭包。不像 PHP 那样半生不熟,您必须在闭包中手动声明要使用的所有变量。

这个 PHP 代码的等价物:

$foo = 'bar';
$fn = function() use($foo)
{
    echo $foo; // bar
}

这是在 JS 中吗:

var foo = 'bar';
var fn = function() {
    console.log(foo);
};

是的。你不是在 PHP 中调用你的函数,为什么我会在 JS 示例中调用它? :-)

顺便说一句,如果你在 JS 控制台中运行这段代码:

var foo = 'bar';
var fn = function() {
    console.log(foo);
};
fn();

您将看到记录了“栏”。证明闭包不需要一些技巧就可以工作。 (use)

关于全局变量:$foo 变量在您的 PHP 示例中是全局变量。它们也在 JS 示例中。如果你想要一个非全局变量,你需要一个本地环境。大多数时候,一个函数。

非全局变量的 PHP 示例:

function baz() {
    $foo = 'bar';
    $fn = function() use ($foo) {
        echo $foo;
    };
}

带有非全局变量的 JS 示例:

function baz() {
    var foo = 'bar';
    var fn = function() {
        console.log(foo);
    };
}

最后一点:如果您不使用var 在 JS 中声明新变量,它们是隐含的全局变量。在浏览器中,这意味着它们附加在window 对象上。

如果你想比较一下如何声明全局变量的 PHP/JS:

PHP 代码:

$foo; // global
function bar() {
    $_GLOBAL['baz']; // global
    $bin; // local
}

JS代码:

foo; // global
function bar() {
    window.baz; // global
    var bin; // local
    booze; // implied global
}

【讨论】:

  • 您使用的是相同的范围。这就是它在您的示例中起作用的原因。如果您通过其他函数多次传递 fn ,这将不再起作用。但是我的例子真的很糟糕,所以没关系。谢谢!
  • 必须声明捕获的变量并不会减少闭包。
  • 同意,在某些情况下它甚至可以被视为有益的(隐式与显式)
【解决方案3】:

如果你想保持你的窗口对象干净,那么这可能是你需要的。

(function(){

  var foo = 'bar';

  (function(){
      console.log(foo) // bar
  })();

})();

console.log(window.foo); //undefined

【讨论】:

    【解决方案4】:

    答案是在 PHP 中您选择包含的内容。在 JS 中,没有办法告诉闭包选择要包含哪些变量。所有词法可用的变量都被括起来。

    但是很难说你想要什么,看起来你想隐藏一个闭包变量

    唯一的解决方法是隐藏你不想要的变量(通过在内部函数中声明它们)

    【讨论】:

    • 我就是这么想的:(
    • 我想知道 OP 是否希望 .call() 在函数中确定 this 的值(这不一定是闭包问题)?
    • 等等,什么?为什么要隐藏闭包的变量?这是我第一次听到这样的 hack (use) 被提及为功能:-)
    • @FlorianMargaine 它可以节省内存,请注意 Chrome 会进行闭包优化,并且只包含实际使用的内容,除非您在那里有 eval。而且我不想掩盖任何事情,只是想弄清楚一个问得不好的问题
    • 隐藏变量以节省内存?这对我来说是第一次......第二句话似乎否定了第一句话。
    【解决方案5】:

    在您问题的后半部分,您询问了有关致电的问题 this 设置为指定对象的函数。

    要调用函数funthis 设置为objectThatBecomesThis 并将参数设置为(arg1,arg2,...),请使用:

    fun.apply(objectThatBecomesThis, [arg1,arg2,...])
    

    其中第二个参数(可选)是函数的参数数组。

    因为第二个参数是一个数组,所以它使用[]方括号。

    https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/apply

    【讨论】:

      猜你喜欢
      • 2011-07-14
      • 2020-06-06
      • 2015-03-24
      • 2016-08-14
      • 2022-08-19
      • 2019-10-21
      • 2017-12-22
      • 2019-02-10
      • 2020-03-11
      相关资源
      最近更新 更多