0

I tried to write one JavaScript jQuery program that say a number. It represents some records I recorded before. I have one problem. When I type a number, it plays only the last record (the last char of the string). It is the program:

function recognizer (num) {            
        var result = '#';
            switch(num) {
            case '0':
                result += 'zero';
                break;
            case '1':
                result += 'one';
                break;
            case '2':
                result += 'two';
                break;
            case '3':
                result += 'three';
                break;
            case '4':
                result += 'four';
                break;
            case '5':
                result += 'five';
                break;
            case '6':
                result += 'six';
                break;
            case '7':
                result += 'seven';
                break;
            case '8':
                result += 'eight';
                break;
            case '9':
                result += 'nine';
                break;
        }

        return result;
    }     

$('#submit').click(function() {

    var num = $('#number').val();

    var delay = 1000;

    for (var i = 0; i < num.length; i++) {
        var indexNum = recognizer(num[i]);
        setTimeout(function () {
            $(indexNum).trigger('play');
        }, delay);
        delay += 1000;
    }

});
4
  • 4
    That switch statement is an abomination. Why not use an object instead? Commented Feb 7, 2018 at 19:44
  • When I type a number, it plays only the last record -- what do you mean? Commented Feb 7, 2018 at 19:46
  • 2
    That title tho... Commented Feb 7, 2018 at 19:59
  • Your title is completely useless. It should contain some part of the problem. Commented Feb 7, 2018 at 20:02

2 Answers 2

2

The real problem is you have a closure, and when the function is executed, the value of indexNum has been set to the final number. You can break the closure with let or use a Standard-Closure-Breaking-Pattern.

setTimeout((function (indexNum) {
     return function() { $(indexNum).trigger('play'); };
})(indexNum), delay);

Also, your recognizer could be compacted. Assuming num is always a single character string, which it appears it is meant to be given your example.

function recognizer(num) {
   const numberWords = ['zero', 'one', 'two', ...];
   return `#${numberWords[num]}`;
}
Sign up to request clarification or add additional context in comments.

Comments

0

async functions may cause some trouble...

try to create a new instance of vars for each loop:

    var indexNum = recognizer(num[i]);

    (function (indexNum, delay) {
        setTimeout(function () {
            $(indexNum).trigger('play');
        }, delay);
    })(indexNum, delay);

var num = "123456789";

var delay = 1000;

for (var i = 0; i < num.length; i++) {
  var indexNum = recognizer(num[i]);

  // Correct
  (function(indexNum, delay) {
    setTimeout(function() {
      document.write("Correct ", indexNum, " ", delay, "<br>");
    }, delay);
  })(indexNum, delay);

  // Weird
  setTimeout(function() {
    document.write("Weird ", indexNum, " ", delay, "<br>");
  }, delay);

  delay += 1000;
}




function recognizer(num) {
  var labels = [ "zero", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" ];
  return "#" + labels[Number(num)];
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.