简体   繁体   English

匿名函数中的变量未定义

[英]Variable Undefined in Anonymous Function

function updateServerList() {
    var i;

    for (i=0; i < servers.length; i++) {
     var server = servers[i];
     var ip = server['serverIp']


     var html = constructServer(i);
     var divId = '#server' + ip.replace(new RegExp("\\.", "mg"), "-");
     var visible = $(divId).find(".server_body").is(":visible");
     var div = $(divId);
     div.html(html);

     // Set div class.
     var prevState = div.attr('class').substring(7)
     if (prevState != server['state']) {

         if (server['state'] == 'ok') {
         console.debug(server);
         div.slideUp('fast', function(server) {
             $(this).removeClass();
             $(this).addClass('server_ok');
             var id = ipToId[server['serverIp']];
             console.debug(id);
             if (id == 0) {
             adjacentIp = servers[1]['serverIp'];
             adjacentDivId = '#server' + adjacentIp.replace(new RegExp('\\.', 'g'), '-');
             $(adjacentDivId).before(this);
             }
        }).delay(1000);
        div.slideDown();
        }
    }
}

console.debug shows server as being defined, but inside the anonymous function, server is not defined. console.debug server显示为已定义,但在匿名函数内,未定义server What am I going wrong? 我出了什么问题?

because server is an argument to the function, its masking the value of the server at the higher level. 因为server是函数的参数,它掩盖了更高级别的server的值。 You need to either pass server to the function, or remove the function argument. 您需要将服务器传递给函数,或者删除函数参数。 I would do the latter, as slideUp doesn't give you a way to pass arguments. 我会做后者,因为slideUp没有给你一个传递参数的方法。 You could do it but its needlessly complicated; 你可以做到,但它不必要地复杂化; it would look something like the following 它看起来像下面这样

div.slideUp('fast', (function(server) { 
   return function(){ 
      // your stuff here, server is now 'closed in', i.e. in a closure
   }
})(server)); // <-- this server is the current value in the loop

what you are doing here is invoking a new function right away, passing in the argument server, and returning a new function that receives that value. 你在这里做的是立即调用一个新函数,传入参数服务器,并返回一个接收该值的新函数。

var server = servers[i];

var prevState = div.attr('class').substring(7);

if (prevState != server['state']) {

   if (server['state'] == 'ok') {
      console.debug(server);
      div.slideUp('fast', function() {
            ...
         var id = ipToId[server['serverIp']];
     }
}

Inside your anonymous function, "server" is still within the function scope. 在您的匿名函数中,“server”仍在函数范围内。 No need to pass it in as an argument. 无需将其作为参数传递。

The Quick Fix 快速修复

// ...

div.slideUp('fast', function() { // `server` argument removed
    // ...
});

The Explanation 说明

There is no need to pass server to the function. 无需将server传递给该功能。 The anonymous function "closes" over the server variable. 匿名函数“关闭” server变量。


This is merely a function declaration : 这只是一个函数声明

function (server) {...}

You aren't passing anything to the function yet, as it isn't being invoked yet! 你还没有把任何东西传递给函数,因为它还没有被调用 The (server) bit in a function declaration simply lets you name the arguments to your function. 函数声明中的(server)位只允许您为函数命名参数。 Only when you invoke the function can you pass arguments: 只有在调用函数时才能传递参数:

var name = "Jill";
var showName = function (name) {
    alert(name);
};

showName("Jack"); // alert box shows "Jack"
showName(); // alert box shows "undefined"

So, when you declare that the name of the first argument to your anonymous function is server , there is a name conflict which prevents the original from being accessible; 因此,当您声明匿名函数的第一个参数的名称是server ,会发生名称冲突,导致无法访问原始函数; the server in your anonymous function is whatever slideUp passes as the first argument, which, according to the documentation , is nothing , so server is now undefined . 你的匿名函数中的serverslideUp传递的第一个参数, 根据文档 ,它是什么都没有 ,所以server现在是undefined

If this is confusing (and I suspect it is), I would suggest reading about javascript closures. 如果这是令人困惑的(我怀疑它是),我建议阅读关于javascript闭包。 Here's a good place to get started . 这是一个开始的好地方


Fun fact : you can actually access arguments, in order, without having any explicit names, by using Javascript's built in arguments array object inside a function: 有趣的事实 :通过在arguments内部使用Javascript的内置arguments数组对象,您可以按顺序访问参数,而无需任何显式名称:

var sum = function () {
    var i, total = 0;
    for(i = 0; i < arguments.length; ++i) {
        total = total + arguments[i];
    }
    return total ;
};

alert(sum(1,2,3)); // Displays "6"
alert(sum(1,2,3,4)); // Displays "10"
alert(sum(1,0,2,3)); // Displays "6"
alert(sum()); // Displays "0"

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

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