【问题标题】:Javascript closure and handlersJavascript 闭包和处理程序
【发布时间】:2013-05-28 18:05:11
【问题描述】:

我有这个javascript函数:

 function files() {
    var dropResult = false;

    $('#button1').on('click', function() {
           dropResult = true;
    });

    $('#button2').on('click', function() {
          dropResult = false;
    });

   return dropResult;           
}
files();

在我们单击其中一个按钮后,dropResult 变量必须更改。如何正确编写它以使我的函数返回 dropResult 变量的正确值? 我知道,这是关于闭包的,但我真的不明白如何解决这个问题。 感谢您的帮助。

【问题讨论】:

  • 由于files() 返回一个值,我假设您打算多次调用它。但是在函数本身中,您正在绑定点击事件。您真的是要在每次调用函数时绑定它们吗?如果没有进一步的上下文,似乎根本不应该有一个函数。 dropResult 应该只是全局的,并且应该在页面加载时绑定点击事件。
  • 什么是正确值?
  • dropResult 不在全局范围内

标签: javascript jquery closures


【解决方案1】:

我相信你想要

var files = (function () {
    var dropResult = false;

    $('#button1').on('click', function () {
        dropResult = true;
    });

    $('#button2').on('click', function () {
        dropResult = false;
    });

    return function () {
        return dropResult;
    };
})();

http://jsfiddle.net/gaby/9b7yK/的演示

【讨论】:

    【解决方案2】:
        var dropResult = false;
    
        $('#button1').on('click', function() {
               dropResult = true;
        });
    
        $('#button2').on('click', function() {
              dropResult = false;
        });
    
        function files() {
           return dropResult;           
        }
    

    假设您只需要获取dropResult 的正确值,上述代码应该可以工作。

    【讨论】:

      【解决方案3】:

      我将“扩展” Gaby aka 的答案,但我认为他是完全正确的。我只会更具体地介绍私有和公共方法。以及如何访问它们,实际上还将事件绑定到特定按钮,您可以在此处查看小提琴 [http://jsfiddle.net/qsDz6/][1]

      HTML

      <input type="button" id="button1" value="button 1" />
      <input type="button" id="button2" value="button 2">
      
      <input type="button" id="actualValue" value="Actual Value of _dropResult">
      

      JS

      var files = (function(__name){
           var _name = __name;
           var _dropResult = null;
      
          /*Private  */
          function init(){
              eventHandler();
          }    
      
           function eventHandler(){
             $(document).on("click","#button1", $.proxy($r.actionButton1,this));
             $(document).on("click","#button2", $.proxy($r.actionButton2,this));
             $(document).on("click", "#actualValue", $.proxy($r.dropResult,this));
           }
      
          /*Public */
           var $r = {}; //will make public any method
      
           $r.actionButton1 = function(){         
             _dropResult = true;        
             alert(_dropResult);
           }
      
           $r.actionButton2 = function(){
             _dropResult = false;         
              alert(_dropResult);
           }        
      
           $r.dropResult = function(){alert(_dropResult);}
      
      
           init();    
      
           return $r;    
      })("files");
      

      愉快的编码

      【讨论】:

        【解决方案4】:

        更新:尽管事实上投票最多的解决方案是同时发布的,但这个答案以某种方式被否决了,同样优雅,并且在逻辑上是等效的。另一种解决方案只是选择在函数闭包而不是对象闭包中捕获局部变量。

        作为选民的责任是实际阅读和思考这些解决方案的作用,而不是仅仅为熟悉的人或声望最高的人提供的答案投票。

        我的回答责任是只回答不是为了人气竞赛的问题,而是在 (A) 我确定一个有效的答案并愿意花时间解释和维护该答案时;或 (B) 对于一些没有什么比“答案”更明确的讨论问题,只有当我在我的经验中多次遇到这个问题并根据我的实际经验对此有话要说时。

        出于这个原因,即使社区中的某个人在没有任何解释的情况下匿名决定否决它,我也会留下我的答案(就像我过去所做的那样)。

        请记住,Stack Overflow 上的答案旨在成为有用问题的有用解决方案的存储库,以造福于未来的所有程序员。值得展示两种不同的方法,而不是单一的。

        是的,另一个解决方案很优雅,并且很好地演示了使用匿名函数闭包捕获局部变量。然而,在我看来,我的解决方案在 Stack Overflow 的目的方面稍微好一些,因为这个解决方案可以很容易地修改为一个可重用的函数来创建许多监控变量。另一种解决方案需要一些反卷积,以使其对一个监控功能的多个静态实例有用。

        function files() {
            var dropResult = {};
        
            $('#button1').on('click', function() {
                   dropResult.result = true;
            });
        
            $('#button2').on('click', function() {
                  dropResult.result = false;
            });
        
           return dropResult;           
        }
        var dropObject = files();
        

        变量dropObject 是一个“监控变量”,可以在任何地方使用,以检查您所监控的内容的状态(在这种情况下,用户最近一次单击按钮1 或按钮2.)

        在使用来自files() 的结果的代码中,您可以这样做

        if (dropObject.result) {
            /* do something here that you want to do when the result is true */
        
        } else {
            /* do something here when the result is false */
        }
        

        我建议存储比truefalse 更有意义的内容(例如,如果您想添加第三个按钮,然后监视最后点击三个按钮中的哪一个?)。

        注意:以下是我将如何编写一个更小、更高效的可重用监控函数供我使用(不在函数内硬连线任何参数或名称)并将其应用于此场景:

        function clickMonitor(ids) {
        var i, f = function() { i = this; }; ids = ids.match(/(\S+)/g) || [];
        for (i=0; i<ids.length; i++)
        document.getElementById(ids[i]).onclick = f;
        return function() { return i; };
        }
        

        下一部分只是创建一个dropResult 变量,它是 “即插即用”代替您的 dropResult 变量,除了您 必须检查dropResult() 是真还是假 (函数调用)而不仅仅是dropResult

        dropResult = (function() {
        var x = clickMonitor('button1 button2');
        return function() { return x().id == 'button1'; };
        })();
        

        一般来说,这是您使用它的方式(当然,如果需要,可以将两个以上的按钮 ID 传递给它):

        getMostRecentClickedButton = clickMonitor('button1 button2');
        

        调用getMostRecentClickedButton()会返回整个按钮 最近单击的对象,以便您可以对它执行某些操作,例如 使字体加粗等,无需执行另一个中间 jQuery 或 JavaScript 程序。

        【讨论】:

          【解决方案5】:

          我不明白这样做的必要性,但一种方法是

          function files() {
             files dropResult = false;
             return files.dropResult;           
          }
          $(document).on('click', '#button1', function() {
            files.dropResult = true;
          });
          
          $(document).on('click', '#button2', function() {
            files.dropResult = false;
          });
          files();
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2017-10-16
            • 2010-09-25
            • 1970-01-01
            • 2017-02-20
            相关资源
            最近更新 更多