【问题标题】:Javascript scope issue: variable not being identifiedJavascript范围问题:未识别变量
【发布时间】:2011-09-03 07:19:26
【问题描述】:

我有两个函数,一个函数调用另一个函数。

下面是我创建的代码结构的一个简单类比:

function test1(){
    alert(a);//a is not identified here even when test1() is called under test2 which has a defined in scope
    alert(b);//b is identified here
}

function test2(){
    var a       =       'a';//Defining a
    test1();//Calling test1()
}
var b   =   'b';
test2();

根据上面的代码,函数 test1() 能够识别变量 b 但不能识别变量 a。

我的问题是为什么变量 a 不在 test1 函数的范围内,即使我们在定义变量 a 的 test2() 中调用 test1() ?

提前致谢。

【问题讨论】:

    标签: javascript function scope


    【解决方案1】:

    函数在创建时记住其作用域链,而不是在调用时记住。

    注意b 得到"hoisted",所以你的代码实际上是这样做的:

    var b; // push b on scope chain
    
    function test1(){ // store scope chain [b]
        alert(a);
        alert(b);
    }
    
    function test2(){ // store scope chain [b]
        var a; // push a on scope chain
        a = 'a';
        test1(); //Calling test1() which still has scope chain [b], not [b,a]
    }
    b   =   'b';
    test2();
    

    【讨论】:

    • "函数在它们被创建时记住它们的作用域链,而不是在它们被调用时。"这似乎是整个问题的症结所在。
    【解决方案2】:

    您对变量范围的期望是错误的,

    根据您的代码,b 是 2 个函数的全局变量,a 仅在 test2 函数的范围内,因为它是用 test2 定义的, 如果你想要你所期望的东西,你可以像这样在test2 范围内定义test1 函数,

    function test2(){
        var a       =       'a';
        test1();
      function test1(){
          alert(a);
          alert(b);
       }
    }
    var b   =   'b';
    test2();
    

    【讨论】:

    • @NetEmp 有关范围界定的更多信息,请查看wikipedia article。 Javascript 使用词法作用域,因为动态作用域是邪恶的。
    【解决方案3】:

    JavaScript 具有“函数范围”,这意味着函数中定义的任何内容在函数之外都是不可见的。所以变量'a'在test2之外是不可见的。但是,变量 'b' 是一个全局变量,因此它在每个范围内都是可见的。

    函数作用域还意味着内部函数可以访问外部函数中定义的内容,但不会在这里发挥作用...test1 在 test2 中调用,但它不是内部函数test2的功能要看到这一点,您需要在 test2 中定义 test1 函数的主体...

    function test2(){
        var a       =       'a';//Defining a
        test1();//Calling test1()
    
        function test1(){
            alert(a);//a is identified here because of function scope
            alert(b);//b is identified here because it's global
        }
    }
    

    【讨论】:

    • 感谢 IanR,因此只有内部函数可以访问父函数中定义的值,而不能访问被调用函数。
    【解决方案4】:

    使用参数调用函数是一个好习惯。这将使您的代码易于阅读和维护。只需向函数添加参数即可使代码正常工作:

    function test1(a,b){
        alert(a);
        alert(b);
    }
    
    function test2(b){
        var a = 'a';
        test1(a,b);
    }
    var b = 'b';
    test2(b);
    

    如果你不想在函数声明中使用参数,一个解决方案是在代码中使用arguments object

    function test1(){
        alert(arguments[0]);
        alert(arguments[1]);
    }
    
    function test2(){
        var a = 'a';
        test1(a,arguments[0]);
    }
    var b = 'b';
    test2(b);
    

    如果您愿意,可以创建arguments with default values。由于在 JavaScript 中你不能在函数参数列表中完成,它是在函数体中完成的:

    function test1(a,b){
        a = a || 'a';
        b = b || 'b';
        alert(a);
        alert(b);
    }
    function test2(b){
        var a = 'a';
        test1(a);//here b is not passed to the function and b will get the default value
    }
    var b = 'some new string for b';
    test2(b);
    

    直播jsfiddle

    【讨论】:

      【解决方案5】:

      根据您在函数“test2()”中声明并定义变量“a”的函数,因此变量“a”的范围”被限制在该函数本身内,访问该变量将返回“undefined”。但它不是在全局声明和定义的变量“b”的情况下,因此可以在脚本部分的任何位置访问它。

      希望对你有所帮助。

      【讨论】:

        猜你喜欢
        • 2011-04-13
        • 1970-01-01
        • 1970-01-01
        • 2017-07-18
        • 2010-11-08
        • 1970-01-01
        • 1970-01-01
        • 2011-09-16
        • 2015-07-20
        相关资源
        最近更新 更多