【问题标题】:How can I use closures with function pointers?如何使用带有函数指针的闭包?
【发布时间】:2012-11-13 01:13:24
【问题描述】:

我的目标是在编写干净代码的同时使用闭包。我注意到的一件事是,不知何故,我总是以某种方式重复自己,因为在不止一种情况下需要我的一个匿名函数。

为了这个目标,我想将这些重复的函数存储在一个对象中,以便以后重复使用。

现在,我的问题。我已经创建了这个示例 http://jsfiddle.net/tiagoespinha/tTx64/ 并且不会触发警报,因为 y 为空。

但是,如果我内联函数,一切正常http://jsfiddle.net/tiagoespinha/tTx64/1/

有什么技巧可以解决这个问题吗?我怎样才能让它在第一个例子中工作?变量y还在,为什么JS抓不到?

【问题讨论】:

  • 这正是闭包的工作原理。如果您定义一个函数,它可以访问它定义的范围。在这种情况下,您希望访问来自不同范围的变量。在函数式编程中,最简单的解决方案是让函数通过参数访问这个变量。

标签: javascript closures


【解决方案1】:

您希望对象拥有自己的变量 (y) 和共享函数。

你真正需要的可能是原型。

function Holder() {
   this.y = 5;
   this.myFn();
}
Holder.prototype.myFn = function() {
    alert("The value of the closure var is " + this.y);           
}
new Holder();

我建议阅读 Introduction to Object-Oriented JavaScript,这样您就不会尝试仅通过闭包来重建 OOP。

【讨论】:

  • 感谢您的解决方案!我怀疑我正在做的事情不是直接可能的,而且我之前确实遇到过这个问题,但这证实了这一点。干杯!
【解决方案2】:
//our constructor, each instance will carry a y of 5
function Proto() {
    this.y = 5;
}

//a shared function for all instances
Proto.prototype.returnedFn = function() {
    alert("The value of the closure var is " + this.y);
}

//just a wrapper for the new instance call.
//I just like it this way to avoid using "new" when making instances
function newFn() {
    //return a new instance
    return new Proto();
}

//test it out
newFn().returnedFn();
newFn().returnedFn();

【讨论】:

  • 也感谢您也提供解决方案!
【解决方案3】:

您的第一个示例需要某种动态范围 才能工作。 Javascript 是静态作用域的。

闭包允许函数从其定义的范围内捕获一些局部变量。Holder.myFn 未在包含变量 y 的范围内定义。

还要注意,函数的每个实例都有自己的闭包。因此,不可能一次定义您的函数并让它在不同的上下文中引用不同的y。 (在您的第二个示例中,每次您调用 newFn 都会定义内部函数,因此可以存在许多实例,每个实例都有自己的 y 副本。)

【讨论】:

  • 现在说得通了。范围在定义函数时解决,而不是在执行时解决。谢谢你的解释!
【解决方案4】:

我还将添加我自己的问题的答案以报告我的发现。

基于提供的其他解决方案并部分使用 OOP 解决方案,我找到了另一种也使用闭包的方法。

// Object prototype which takes an argument 
function MyObj(abc) {

    // Declare function using a closure
    // and thus being able to use the argument
    this.myFn = (function(){
        return function() {
            alert("abc is " + abc);
        };
    })();                
}

// Then we can simply create an object with the
// desired argument and the function will behave as expected
var v = new MyObj(10);
v.myFn();

我认为没有人提供此解决方案可能是因为我忽略了我真的不想将值本地存储在对象中。我只是想传入一些值,在一个函数中使用它们,然后摆脱该对象。

在这种情况下,我认为纯粹的 OOP 解决方案可能有点矫枉过正。

无论如何,感谢您提出的所有解决方案!​

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-12-27
    • 1970-01-01
    • 2017-07-23
    • 2012-12-11
    • 2012-05-06
    • 1970-01-01
    • 1970-01-01
    • 2011-10-27
    相关资源
    最近更新 更多