【问题标题】:Closure inside a loop in JavascriptJavascript中循环内的闭包
【发布时间】:2018-06-10 14:36:33
【问题描述】:

我有一个简单的函数,它的 for 循环中有另一个函数。主函数返回子函数。调用主函数时,循环运行,但子函数尚未执行,因为它尚未被调用。循环执行后调用子函数,因此i 的值指向数组最后一个元素的值。如果我希望它对数组中的每个值都有一个新的绑定,我该如何解决?

function getName() {
    const arr = ['a', 'b', 'c', 'd'];
    for (let i = 0; i < arr.length; i++) {
        function sendName() {
            alert(arr[i]);
        }
    }
    return sendName;
}
var receiveName = getName();
receiveName();

【问题讨论】:

  • 您的要求似乎没有意义。您对getName() 进行一次调用,它会返回一个稍后调用的函数。那个单一的调用怎么会有“对每个值的新绑定”?这是来自getName() 的单个结果。也许你可以返回一个函数数组?
  • 你的代码甚至不能在严格模式下工作,就像functions are block-scoped。您返回的 sendName 变量不存在。这是您更大问题的一部分:您的 getName() 仅返回一个函数。您甚至如何调用指向不同索引的不同函数(由于您在循环中使用了let,这实际上已经起作用了)。

标签: javascript jquery html closures


【解决方案1】:

您可能想改用匿名包装器:

function getName() {
    const arr = ['a', 'b', 'c', 'd'];
    for (let i = 0; i < arr.length; i++) {
        (function() {
            alert(arr[i]);
        })(i);
    }
}
getName();

另外,正如其他人在 cmets 中提到的那样,在您提供有关您为什么需要它的更详细解释之前,这种实现几乎没有意义。可能应该有更优雅的解决方案来满足您的要求。

【讨论】:

  • 在这里使用 IIFE 没有意义。尤其是如果您无论如何都要立即发出警报。
  • @Bergi 不知道作者的意思和功能实现。
  • @Oleksandr 那你应该发表评论询问细节,而不是写一个没有意义的答案。
  • @Bergi 你是对的!让 Kshri 接受一个更好的解决方案的答案,我会很乐意删除我自己的。
【解决方案2】:

你可以使用bind函数来实现你想要的:

function sendName( name ) {
  alert( name );
}

function getNames() {
  const arr = [ 'a','b','c','d' ];
  let sendNames = []; //Dunno what you want to do with this functions so let's store them in an array
  for(let i = 0; i < arr.length; i++) {
    sendNames.push(sendName.bind(this, arr[i])); // this - context, later arguments
  }
	return sendNames;
}
var receivedNames = getNames();
receivedNames[1](); //b
receivedNames[3](); //d

【讨论】:

  • 当您对我的回答投反对票时,请在评论中添加反馈,以便我了解问题所在。
  • 为什么这么复杂? OP 创建函数的代码已经可以工作了,只有数组的那位不行。
  • @Bergi另外一种情况,使用自调用功能,你可以直接调用alert(arr[i]),我认为问题的本质是如何延迟调用到以后的时间
  • 你绑定的this是什么?
  • @charlietfl 这是当前的函数范围/上下文。在这个例子中,这并不重要,因为我们没有直接在 sendName 函数中使用它,我们只关心对参数进行柯里化
【解决方案3】:

您可以使用数组来存储不同的函数。这个例子会根据N返回不同的字母。

function getName() {
const arr=['a','b','c','d'];
  let a = [];
	for(let i = 0;i<arr.length;i++) {
		a.push(function () {
			alert(arr[i]);
		});
	}
	return a;
}
var receiveName=getName();
let N = 0; // returns a
receiveName[N]();
console.log(receiveName);

希望对你有帮助

【讨论】:

  • 如果你在循环头中保留了let i 声明,你就不需要临时的l 变量。
  • 是的,谢谢我修改了答案
【解决方案4】:

我认为没有必要将 alert(a[i]) 包装在函数范围内,因为我们已经在使用 let 并且它提供了块范围。

我们可以只使用以下函数,它可以输出所需的结果。

function getName() {
    const arr = ['a', 'b', 'c', 'd'];
    for (let i = 0; i < arr.length; i++) {
            alert(arr[i]);
    }
}
getName();

【讨论】:

    【解决方案5】:

    这是因为它只被调用一次,即...... 虽然

    function sendName(){
     alert(arr[i]);
        }
    

    sendName 四次更改其分配的值,但它只被调用一次,因此它只警告“d”,因为 d 是最后分配的值。 如果要提醒“a”、“b”、“c”、“d”,请在循环内调用函数。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-02-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-10
      相关资源
      最近更新 更多