Javascript:setTimeout在嵌套(双)for循环中的闭包

时间:2016-10-05 23:32:40

标签: javascript jquery closures settimeout

您好我正在尝试重新创建http://austintexas.wayblazer.com/locations/austin-tx正在为其搜索文本框执行的操作 - 显示键入的字符并在多个短语之间旋转。

我最初的逻辑是从类似的数组中读取短语:[abc,123,XYZ]然后使用splitforEach将字符串分隔成字符并使用{1}创建输入效果setTimeout

然而,当我尝试这种逻辑时,我似乎无法获得所需的效果。我已经在SO上阅读了很多这些问题,但很少有人解决嵌套for循环的问题。

期望的结果:

  • a b c(按字符输入效果)
  • clear textbox
  • 1 2 3(按字符打字效果)
  • clear textbox
  • X Y Z

实际结果:

  • abc123XYZ(abc一起显示,然后是123,然后是XYZ)



$(document).ready(function() {

  $('input#123').attr("placeholder", "");
  var phrases = ['abc', '123', 'XYZ'];

  for (var i = 0; i < phrases.length; i++) {
    $('input#123').attr("placeholder", "");
    (function(ind) {
      var sentence = phrases[ind];
      sentence.split("").forEach(function(char, index) {
        setTimeout(function() {
          $('input#123').attr("placeholder", $('input#123').attr("placeholder") + char);
        }, ind * 500);
      });
    })(i);
  }
});
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<input id="123" />
&#13;
&#13;
&#13;

对于我想要达到的目标,是否有一个优雅的解决方案,希望能得到一些解释来启发我将非常感激!

2 个答案:

答案 0 :(得分:3)

javascript的优点是闭包,所以你可以创建函数闭包,然后按下数组就像堆栈一样..然后你可以在setInterval中弹出这些函数..

$(document).ready(function(){
	var input = $('input#123'),
	    phrases = ['Stack Overflow','Is the place you come','To get help with coding stuff'],
        typedelay = 140,
        waitops = 5,
        cmds = [],
        ph = input.attr.bind(input, 'placeholder');
  
    function clear() {
      ph('');
    }
  
    function addLetter(a) {
      return function () {
        ph(ph() + a);
      }
    }
  
    function doLoop() {
      cmds = [];
      for (var i=0; i<phrases.length;i++) {
        cmds.push(clear);
        var sentence = phrases[i];
        sentence.split("").forEach(function(char,index) {
          cmds.push(addLetter(char));
        });
        //at the end of each sentence, there is a pause. lets do some no ops,.. 5*300 ms
        for (var nn = 0; nn < waitops; nn ++) cmds.push(0);
      }
      //lets make this thing go on forever.. :)
      cmds.push(doLoop);
    }
      
    doLoop();
  
    var icheck = setInterval(function () {
      //is there a cmd waiting, pop it and run it.
      var cmd = cmds.shift();
      if (cmd) { cmd(); }
    }, typedelay);
  
    input.focus(function () {
      clearInterval(icheck);
      cmds = [];
      ph('What your want');
    });
    
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<input id="123" />

答案 1 :(得分:1)

这是一个递归函数,它移动数组并在数组没有长度时停止

&#13;
&#13;
typePhrases(['Message #1','Another message','And the last one'], 300)

function typePhrases(phrases, speed){
  // shift array to get word/phrase
  var word = phrases.length && phrases.shift(), $input= $('#test').attr('placeholder','');
  // don't do anything if no phrase/word
  if(word){    
    word.split('').forEach(function(char, i){
       setTimeout(function(){
          // use attr(attributeName, function) to update
          $input.attr('placeholder', function(_, curr){
               return curr + char;
          });
          // on last letter call function again to get next word
          if(i=== word.length-1){
            setTimeout(function(){
              typePhrases(phrases, speed); 
              },speed);
            }
       },i*speed)
    });
  }   
}
&#13;
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="test" placeholder=''>
&#13;
&#13;
&#13;