【问题标题】:Creating a closure for .setTimeout() inside a for loop在 for 循环中为 .setTimeout() 创建一个闭包
【发布时间】:2016-06-18 12:08:03
【问题描述】:

我正在尝试编写一个 javascript 程序,该程序在单击按钮时将输入元素中的值存储在数组中。该数组是拆分,每个单独的字母添加到一个 span 元素,然后附加到文档中。这个想法是使用 setTimeout 创建一个打字效果。

我在循环中创建闭包时遇到了问题,因此目前 setTimeout 函数总是返回迭代的最终值。

有问题的函数位于代码块的底部,名为 addTextToBoard();

var noteButton = document.querySelector('[data-js="button"]');

noteButton.addEventListener("click",function() {
  var messageIn = document.querySelector('[data-js="input"]');
  var message = messageIn.value;
  postToBoard(message);
});

function postToBoard(val) {
  var noteBoard = document.querySelector('[data-js="noteboard"]');
  var newElement = document.createElement('div');
  newElement.classList.add('noteboard__item');
  noteBoard.appendChild(newElement);
  setTimeout(function(){
    newElement.classList.add('active');
  }, 200);
  addTextToBoard(newElement, val);
}

function addTextToBoard(el, val) {
   var wordArray = val.split('');
   for(i = 0; i < wordArray.length; i++) {
       var letter = document.createElement('span');
       letter.innerHTML = wordArray[i];
       setTimeout(function(x){
         return function() {}
         el.appendChild(letter);
       }(i),1000);
   }
}

我相信我很接近,我只是没有完全理解创建闭包的语法。如果有人可以在正确的方向上戳戳,而不必给出完整的解决方案,那就太好了。

我基本上试图从here 粘贴以下代码 sn-p,但我在此过程中遗漏了一些东西!

setTimeout(function(x) { return function() { console.log(x); }; }(i), 1000*i);

最好的,

杰克

【问题讨论】:

标签: javascript jquery closures frontend


【解决方案1】:

你很接近。

由于“字母”变量发生了变化,您将一遍又一遍地只添加最后一个字母。您需要在setTimeout() 回调函数上“保存”当前字母,一种方法是这样的:

function appendMyLetter(letter) {
  return(function() {
    el.append.Child(letter);
  });
}

function addTextToBoard(el, val) {
   var wordArray = val.split('');
   for(i = 0; i < wordArray.length; i++) {
       var letter = document.createElement('span');
       letter.innerHTML = wordArray[i];
       setTimeout(appendMyLetter(letter), 1000);
   }
}

这样,appendMyLetter() 函数会使用不同的参数(每个字母一个)调用,并返回一个具有正确“存储”值的函数,以供setTimeout() 调用。

编辑

仔细查看您的setTimeout() 代码

setTimeout(function(x){
  return function() {}
    el.appendChild(letter);
}(i),1000);

如果您使用正确的参数并在返回的函数中使用appendChild(),它将正常工作,如下所示:

setTimeout(function(x){
  return(function() {
    el.appendChild(x);
  });
}(letter),1000);

【讨论】:

  • return in setTimeout 没有意义。无处可归
  • 在我的代码中,它调用并返回一个函数给setTimeout。然后将在给定的毫秒数后调用返回的函数。
  • 不...匿名函数会。 IIFE 在里面毫无意义
【解决方案2】:

您可以创建一个立即调用的函数表达式IIFE 来创建一个闭包

 function addTextToBoard(el, val) {
       var wordArray = val.split('');
       for(i = 0; i < wordArray.length; i++) {
          (function(index) {
            var letter = document.createElement('span');
             letter.innerHTML = wordArray[i];
            setTimeout(function(){
             el.appendChild(letter);
            },1000);
        })(i);
        }
    }

【讨论】:

    【解决方案3】:

    我不知道这是否可行,但在这里你可以稍微改变一下操作员:

    letter.innerHTML += wordArray[i];
    

    如果你没有得到你想象的效果,你会得到更好的尝试增加计时器,我喜欢这样

    setTimeout(function(){
     ...
    },1000*i);
    

    【讨论】:

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