Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/417.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在这里创建闭包的替代方案是什么?_Javascript_Closures_Code Readability - Fatal编程技术网

Javascript 在这里创建闭包的替代方案是什么?

Javascript 在这里创建闭包的替代方案是什么?,javascript,closures,code-readability,Javascript,Closures,Code Readability,假设我们有一个简单对象列表: var things = [ { id: 1, name: 'one' }, { id: 2, name: 'two' }, { id: 3, name: 'three' } ]; 我们需要遍历这些对象,并将它们注册为稍后事件的参数。naive方法在所有回调之间共享相同的对象引用,因此每个回调都针对最后一项触发: 但是,在本例中,我们最终创建了一种闭包,将匿名函数传递给forEach() 有没有一种方法可以在不使用闭包或函数引用的情况下完成此操作? 根

假设我们有一个简单对象列表:

var things = [
  { id: 1, name: 'one' },
  { id: 2, name: 'two' },
  { id: 3, name: 'three' }
];
我们需要遍历这些对象,并将它们注册为稍后事件的参数。naive方法在所有回调之间共享相同的对象引用,因此每个回调都针对最后一项触发:

但是,在本例中,我们最终创建了一种闭包,将匿名函数传递给
forEach()

有没有一种方法可以在不使用闭包或函数引用的情况下完成此操作?

根本问题有三个方面:

  • 不那么重要:传递到
    setTimeout()
    的函数引用(或其他任何引用)会让您(我)感觉您在创建一个闭包。所以,我倾向于忘记外部闭包
  • 更重要的是:附加的函数/闭包声明鼓励使用“箭头代码”。对于复杂操作,随着代码从屏幕外迁移,复杂操作的代码可读性会很快恶化。。。IE>9中的
    .forEach()
    可能会解决这个问题,除非应用程序或组织风格指南为闭包指定换行+缩进
  • 最重要的是:我非常确定有一种简单的方法来处理这个问题。我觉得很傻,因为我现在想不起来

  • 也许更好的提问方式是:在我们开始强制创建闭包之前,我们到底做了什么?

    我认为在这里使用闭包没有任何问题。它们是javascript中的自然工具,对于具有本地状态的异步回调非常必要,因为我们希望避免全局状态

    如果您非常关心缩进,那么可以将提供IEFE的范围与循环放在同一行:

    for (var i = 0; i < things.length; i++) (function() {
      var o = things[i];
      setTimeout(function() { doSomethingWith(o); }, i * 1000);
    }());
    
    如果您想要一个非常清晰的代码组织,请明确结束:

    function makeDoer(thing) {
        return function() { doSomethingWith(thing); };
    }
    for (var i = 0; i < things.length; i++) {
        setTimeout(makeDoer(things[i]), i*1000);
    }
    
    函数生成器(东西){
    返回函数(){doSomethingWith(thing);};
    }
    for(var i=0;i
    在我们开始强制创建闭包之前,我们到底做了什么

    我们使用全球国家,以不同的方式解决我们的问题。例如,使用半递归函数可以更好地解决您的问题:

    var i = 0;
    function next() {
        if (i < things.length) {
            doSomethingWith(things[i++]);
            setTimeout(next, 1000);
        }
    }
    next();
    
    var i=0;
    函数next(){
    如果(i
    我想有两种不同的方法。 首先,将参数绑定到此方法的调用。 它克隆函数中的参数things[i]并将其用作参数

    for (var i = 0; i < things.length; i++) {
      var o = things[i];
      setTimeout(doSomethingWith.bind(null, things[i]), i * 1000);
    } 
    
    for (var i = 0; i < things.length; i++) {
     var o = things[i];
     setTimeout(function(param) { doSomethingWith(param); }, i * 1000, o);
    }
    
    for(var i=0;i
    另一方面

    setTimeout在参数时间(毫秒)之后,接受您将调用的函数中的参数,它还会复制定义时的值,因此变量值可以在之后更改,setTimeout将保证将正确的值作为参数传递

    for (var i = 0; i < things.length; i++) {
      var o = things[i];
      setTimeout(doSomethingWith.bind(null, things[i]), i * 1000);
    } 
    
    for (var i = 0; i < things.length; i++) {
     var o = things[i];
     setTimeout(function(param) { doSomethingWith(param); }, i * 1000, o);
    }
    
    for(var i=0;i

    希望有帮助

    +1,但请注意,绑定函数也可以被视为闭包,并且在所有使用全局状态的浏览器中不支持附加的
    setTimeout
    参数。。。我想这就是我要找的。我无法理解我们过去是如何管理这类东西的,以及为什么我会停下来。但是,我很确定就是这样。我们和很多全局对象混在一起。
    for (var i = 0; i < things.length; i++) {
      var o = things[i];
      setTimeout(doSomethingWith.bind(null, things[i]), i * 1000);
    } 
    
    for (var i = 0; i < things.length; i++) {
     var o = things[i];
     setTimeout(function(param) { doSomethingWith(param); }, i * 1000, o);
    }