简体   繁体   English

Javascript:如何在函数内修改全局变量?

[英]Javascript: How to modify global variables within functions?

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? 我想知道为什么,当我更改函数中的变量ttt时,更改不会停留在函数之外? I've declared it as var ttt = new Array; 我已将其声明为var ttt = new Array; at the very top. 在最顶端。

Also, why can't I use the variable i in the function? 另外,为什么我不能在函数中使用变量i

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]);

    });

As you pointed out, there are two separate problems with your code, and they're both somewhat related. 正如您所指出的,您的代码存在两个独立的问题,并且它们都有些相关。 First, ttt is being modified globally. 首先, ttt 正在全球范围内进行修改。 The problem is that you're checking for the modifications before they happen. 问题是你在修改之前检查它们。 I suspect that client.getMatchHistory() is making an asynchronous call. 我怀疑client.getMatchHistory()正在进行异步调用。 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. 无法保证第二个for循环中的所有异步操作都将在执行第三个for循环时执行,在第三个for循环中读取数组。

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. 由于client.getMatchHistory()是异步的,因此一旦循环执行完毕,就会调用回调。 Once the loop's done executing i will have a value of 10 . 循环完成后, i的值为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. 您需要创建一个回调生成函数,它接受i的值,并返回一个可用作回调的函数。 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. 这将捕获当前迭代中i的值,生成的回调将在执行时使用该值。 That should fix your problem with i . 这应该解决您的问题i

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. 首先,所有全局变量都是有效的“窗口”对象字段,因此您可以使用window.ttt来确保使用全局变量而不是本地变量。 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;' 至于变量i:当然,你可以使用它,但最好在本地使用它,定义'var i;' on the top of the function to not spoil global namespace. 在函数的顶部不破坏全局命名空间。

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: client.getMatchHistory可能是异步请求,你希望在循环之后,你将填充ttt数组,为了实现这一点,你必须创建一个在最后一个循环步骤之后运行的处理程序:

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. 在示例中, i_final计数完成请求,它们可以按随机顺序完成,由于异步,所以在决定运行afterloop()时,你不能引用i ,当i_final计数到超过上次执行的请求时,你运行函数应在最后一次请求完成后执行。

Note: please use global vars as less as possible, in your code you used global i without any reason 注意: 请尽可能少地使用全局变量,在您使用全局i代码中没有任何理由

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM