0

Below is the code I'm working on. I'm wondering why, when I change the variable ttt in the function, the changes do not stay outside of the function? I've declared it as var ttt = new Array; at the very top.

Also, why can't I use the variable i in the function?

code:

  client.on('connection', function()
    {
        var sss;
        var aaa;

            console.log('Connected');

        for (i = 0 ; i < 120 ; i++)
            ttt[i] = 0;

        for (i = 0 ; i < 9 ; i++)
        {
                client.getMatchHistory(434582, function(err, result)        
            {
                sss = JSON.stringify(result);
                var myObject = eval('(' + sss + ')');
                console.log (myObject.object.data[i].object.value);

                ttt[myObject.object.data[i].object.value]++;
            });

        }

            for (i = 0 ; i < 120 ; i++)
                console.log ("Record" + i + " Successes: " + ttt[i]);

    });
2
  • Could you clarify your question a bit? What do you mean when you say that the "changes do not stay outside the function?" Also, what do you mean when you ask, "Why can't I use the variable i in the function?" Commented Dec 26, 2012 at 6:45
  • ttt[myObject.object.data[i].object.value]++; This line should change the ttt array. and it does -- in the function. But outside the function, later: console.log ("Record" + i + " Successes: " + ttt[i]); only displays as 0, no matter what. as for i not working... in the function, the i in console.log (myObject.object.data[i].object.value); always returns as undefined and crashes. If I replace i with a number, such as 0, it works. Why can't the function reference/recognize i from for (i = 0 ; i < 9 ; i++) Commented Dec 26, 2012 at 6:48

3 Answers 3

2

As you pointed out, there are two separate problems with your code, and they're both somewhat related. First, ttt is being modified globally. The problem is that you're checking for the modifications before they happen. I suspect that client.getMatchHistory() is making an asynchronous call. There's no guarantee that all the asynchronous operations in the second for loop will be done executing by the time you execute the third for loop, where you read the array.

The second problem is one of scope, but it's not global scope that's your problem. Since client.getMatchHistory() is asynchronous, the callbacks will be called once the loop is done executing. Once the loop's done executing i will have a value of 10. Likely this is not what you intended. You need to create a callback generating function, that takes the value of i, and returns a function that can be used as a callback. Like this:

function make_callback(i) {
  return function(err, result) {
    // The body of your callback in here
  };
}

And then you should use it like this in the body of the loop:

client.getMatchHistory(434582, make_callback(i))

This will capture the value of i in the current iteration and the generated callback will use that value when executed. That should fix your problem with i.

Sign up to request clarification or add additional context in comments.

Comments

0

First of all, all globals variables are effectively 'window' object fields, so you can use window.ttt to be sure you are using global variables instead of local. This code should work, so did you try it in developer tool? what does debugger say about presence of such variable?

As for variable i: sure, you can use it, but it better to use it locally, defining 'var i;' on the top of the function to not spoil global namespace.

6 Comments

It's not quite true that all variables that are effectively global are attributes of the window object. Variables declared with var before all other script includes are effectively "global" (i.e: they can be accessed and modified by all code subsequently declared/loaded), but they're definitely not attributes of the window object.
@David-SkyMesh That's incorrect. Even if you declare a global variable with var, e.g., var my_global, you can still access it via window.my_global.
@seliopou No you can't. I encourage you to check first.
@seliopou It would seem you are correct. I think I've somehow gotten the wrong impression through some experiments with MozRepl - abstraction leakage of some sort.
@David-SkyMesh I suspected that was the case. JavaScript dev tools frequently "break" scoping behavior, usually because they use the with keyword, which is almost as bad as eval and even less understood. No harm done.
|
0

The client.getMatchHistory probably asynchronous request, you expect that after loop, you will have filled ttt array, to acheive this you have to make a handler which run after last loop step:

var afterloop=function() {
    for (var i = 0 ; i < 120 ; i++)
       console.log ("Record" + i + " Successes: " + ttt[i]);
}
for (var i = 0 ; i < 120 ; i++)
        ttt[i] = 0;

var i_final=0;
for (var i = 0 ; i < 9 ; i++)
        {   
            var i=i;   //localise i
            client.getMatchHistory(434582, function(err, result)        
            {
                i_final++;
                sss = JSON.stringify(result);
                var myObject = eval('(' + sss + ')');
                console.log (myObject.object.data[i].object.value);

                ttt[myObject.object.data[i].object.value]++;
                if (i_final>8) {afterloop();}
            });

        }

in the sample, i_final counts done requests, they can be done in random order, due to async, so you can't refer to i when deciding to run afterloop() , when i_final count to more than last executed request, you run function that should be executed after last request is done.

Note: please use global vars as less as possible, in your code you used global i without any reason

3 Comments

Reference errors on window. I'm not running this in a browser, but using Node.js... is that a problem?
why you need gloval var then ? add var ttt=[]; where you invoke the function
Some really good responses. Thanks. Sifting through everything. By the way, eicto, your solution worked, I have only been programming JS for 3 days but that really helped me learn more about it.

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.