变量如何超出作用域?

4
我有以下jQuery代码:
$.ajax({
    url: 'somefile.php',
    type: "POST",
    data: "",
    dataType: "json",
    async: false,
    success: function (data) {
                var var1  = something;
                var var2  = something;
                var var3  = something;
                var var4  = something;
                for (var i = 0; i < data.length; i++) {
                    $('.somediv').html('');
                    $('.somediv').append('Somehtml');
                }
                some_function_declared_later(var1, var2, var3, var4);
             }

编译时出现错误:'var1','var2','var3' 和 'var4' 超出范围。然而,我看不出问题,因为它们在相同的函数中声明并使用。

请帮忙!

更新: 这与之后声明的some_function_declared_later是否在当前函数外有关吗?


4
编译时出现错误。编译什么?用什么进行编译? - T.J. Crowder
2
@DavidHedlund:这是JavaScript。var总是在函数作用域(或全局作用域,如果在任何函数之外使用)创建变量。 - T.J. Crowder
这些变量应该在作用域内,因为JS具有函数级作用域而不是块级作用域,尽管如果data.length恰好为0,则它们都将具有值undefined。我建议无论它是否在JS中起作用,声明循环内的变量都是不好的做法,特别是如果您随后在循环外部使用它们。 - nnnnnn
2
即使从神秘编译器中删除错误,这段代码也没有意义。你在循环中分配和重新分配变量,然后在循环外部使用它们。因此,它们要么是未定义的(如果data.length为0),要么是最后一次循环的值。 - T.J. Crowder
哦,当然。不用理我,我去拿杯咖啡。 - David Hedlund
显示剩余6条评论
1个回答

7
更新:你提出的新问题完全改变了原来的问题,因此“编译器”错误提示是毫无意义的。我很难相信任何工具会按照你引用的代码给出这个错误,恕我直言,我认为你输入的代码可能与你所想的不同。

你原来的问题中,success处理程序的代码如下:

function (data) {
    for (var i = 0; i < data.length; i++) {
        var var1  = data[i][0];
        var var2  = data[i][1];
        var var3  = data[i][2];
        var var4  = data[i][3];
        $('.somediv').html('');
        $('.somediv').append('Somehtml');
    }
    some_function_declared_later(var1, var2, var3, var4);
 }

...下面的答案与该代码相关。使用您问题中的最新版本。

原始答案:

您在评论中说,“编译器”是“我的网络主机提供的一些在线工具”。

您是完全正确的,这些变量确实在作用域内。要么该工具不理解JavaScript,要么它确实理解,但比语言更严格地进行“lint”处理。例如,jslint将给出类似于此错误(“不要在循环中声明变量”)。 (注意:jslint会给您许多实际上只是作者对事物应该如何完成的意见的“错误”)。在JavaScript中,使用var声明的变量在整个函数内都已声明,因为JavaScript当前没有块作用域,仅有函数作用域和全局作用域。您的success处理程序代码与此完全相同

function (data) {
    var var1, var2, var3, var4;
    for (var i = 0; i < data.length; i++) {
        var1  = data[i][0];
        var2  = data[i][1];
        var3  = data[i][2];
        var4  = data[i][3];
        $('.somediv').html('');
        $('.somediv').append('Somehtml');
    }
    some_function_declared_later(var1, var2, var3, var4);
 }

更多内容请访问我的博客:可怜被误解的var

即使将神秘编译器中的错误排除,这段代码看起来也很奇怪。您正在在循环中赋值和重新赋值变量,然后在循环外部使用它们。因此,它们要么是未定义的(如果data.length0),要么是循环最后一次经过时的值。


关于您的编辑:

这是否与当前函数之外声明的some_function_declared_later有关???

不是。如果问题是some_function_declared_later在那行代码之前没有被定义,那么错误会抱怨some_function_declared_later而不是这些变量。

函数声明(如var语句)会被提升到它们出现的作用域的顶部。因此,如果您在下面添加以下内容:

function some_function_declared_later(a, b, c, d) {
    // ....
}

如果除了一些奇怪的循环之外,你感觉还好。

如果你在下面有这个

var some_function_declared_later = function(a, b, c, d) {
    // ....
};

如果使用了变量声明关键字var,则在代码中后声明的some_function_declared_later函数会被声明,但如果success处理程序在将函数赋值给some_function_declared_later变量的代码行之前运行,它可能具有值undefined。(尽管这种情况可能性很小,但为确保准确性最好不要这样写。)

代码一直有效,但我担心那个警告! - kmdhrm
@DipakYadav:如果你使用的是你问题中最新版本的代码,即使是像jslint这样超级严格的工具,你也不应该收到那个警告。 - T.J. Crowder

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接