0

I have the following JavaScript Code:

for (var x = 0; x < queue.length; x++) {
    var song = new Song().loadJSON(queue[x]);
    //Not already loaded
    if (loaded.indexOf(song.url) == -1) {
        addRow("play", song.url, song.title, song.album, song.artist);
        loaded.push(song.url);
        songs.push(song);
        if (song.duration == 0) {
            var audio = $("<audio>");
            audio.attr("songid", songs.length - 1);
            console.log("Writing:", audio.attr("songid"));
            audio.on("durationchange", function () {
                var id = audio.attr("songid");
                console.log("Reading:", id);
                songs[id].duration = audio[0].duration;
            });
            audio.attr("src", song.url);
        }
    }
}

This prints out:

Writing: 0 
Writing: 1 
Writing: 2 
(3x) Reading: 2 

Which leads me to believe that the songid attribute is being written over in each iteration of the for loop. I am not sure how this is possible because the audio variable is local to each iteration. What am I doing wrong?

Franz Payer
  • 4,069
  • 15
  • 53
  • 77
  • What makes you believe that the `audio` variable is 'local'? – a better oliver Jul 01 '13 at 18:34
  • 3
    JavaScript has *only* function scope (or global scope). Blocks don't create scope. Also, welcome to JavaScript closures! – Felix Kling Jul 01 '13 at 18:35
  • @zeroflagL it was created in that loop. I do not have a reference to it anywhere outside of the loop. Doesn't that make it local? – Franz Payer Jul 01 '13 at 18:36
  • 1
    You're assuming that a block creates a local variable scope. It doesn't. –  Jul 01 '13 at 18:37
  • @FelixKling ok, thanks. That makes more sense now. – Franz Payer Jul 01 '13 at 18:37
  • 1
    @Franz: All variable declarations are *hoisted*. That is, if you put `var foo = ...;` anywhere in the code, it is as if you had written `var foo;` at the top of the script or function. Or to put it in other words: Before a function is executed, the engine collects all variable (and function) declarations and creates a binding for each of them in the function's environment. The technical description of the process can be found in the specification: http://es5.github.io/#x10.5 (step 8). – Felix Kling Jul 01 '13 at 18:37
  • 1
    FWIW, you can solve the problem easily in your case by using `$.each` to iterate over the array. Because then you are executing a function per iteration (i.e. create a new scope per iteration). – Felix Kling Jul 01 '13 at 18:46
  • @FelixKling thanks, that fixed it right away. JavaScript really differs in the way their scope works vs most other languages. If you want to post that as an answer, I will accept it. – Franz Payer Jul 01 '13 at 18:52

1 Answers1

0

var audio = $("<audio>"); is global Variable or in global Scope right now unless for loop is inside a function.

if and for doesnt create a new scope, therefore, variable audio gets written over.

So your belief is correct.

Only variables in function are in new scope, or parameters passed to function.

http://www.adequatelygood.com/JavaScript-Scoping-and-Hoisting.html

Ex:

var someVariable; //global scope.
function abc () {
  var someVariable; //in new scope.
}
or
var fn = function () { var inNewScope;};

Other way to create new scope

callingFunction(parameter); 

variable parameter would be in inner new scope of this function.

Other useful link: http://bonsaiden.github.io/JavaScript-Garden/

Hoisting: When declaration of variables, not assignment, & function Declaration get moved to top most part of scope they were defined in.

Closure: When variables from outer scoper are kept alive even though scope itself doesnt exist. Usually when inner scope access variable that resides in outter scope. Ex: if there is function that returns another function and this returned funcitons uses a variable that was defined its parent function and not in it then reference to that function keeps that variable alive even though that parent function has returned and no longer exists.

To learn More try this: http://javascriptweblog.wordpress.com/2010/07/06/function-declarations-vs-function-expressions/

Muhammad Umer
  • 2,228
  • 2
  • 18
  • 17