简体   繁体   English

如何从 JavaScript 的外部作用域访问变量

[英]How to access a variable from outer scope in JavaScript

In the example bellow, I am trying to access the x that is in the function outer.在下面的示例中,我试图访问函数外层中的x

I was expecting to get 20 as an output, however the output is undefined .我期望得到 20 作为输出,但是输出是undefined

Can someone explain why is that happening, and is there a way to access the outer x?有人可以解释为什么会发生这种情况,有没有办法访问外部 x?

var x = 10;
function outer() {
    var x = 20;
    function inner() {
        var x = 30;
        function printX() {
            console.log(outer.x);
        }
        printX();
    }
    inner();
}
outer();

Scopes aren't designed like that in JavaScript.作用域在 JavaScript 中不是这样设计的。 In order to attach the variable x to its scope, you would need to reference the object for that scope either by name or by this reference.为了将变量 x 附加到其作用域,您需要通过名称或通过此引用来引用该作用域的对象。

What is happening in your example is that your call to printX attempts to log the variable x attached to the function outer.您的示例中发生的情况是您对 printX 的调用尝试记录附加到函数外部的变量 x 。 functions derive from objects in JavaScript, and as a result they may have properties attached to them, so instead of giving you a reference error, you get undefined instead, as the variable does not exist.函数从 JavaScript 中的对象派生,因此它们可能具有附加到它们的属性,因此不是给您一个引用错误,而是您得到 undefined,因为变量不存在。

For more information on scoping, please see my answer on scope in JavaScript .有关作用域的更多信息,请参阅我对 JavaScript 作用域的回答

var x = 10; // Globally scoped variable named "x"
function outer() {
    var x = 20; // Locally scoped to outer function variable named "x"
                // in outer function, this variable takes precedence over the
                // globally scoped x which was 10
    function inner() {
        var x = 30; // Locally scoped to inner function variable named "x"
                    // in inner function, this variable takes precedence over the
                    // parent scoped x which was 20
        function printX() {
            console.log(outer.x); // Tries to read "x" property of the outer function
                                  // If this had been console.log(x) it would give 30 because it is scoped to the function inner's variable environment
        }
        printX();
    }
    inner();
}
outer();

As for what to do going forward, it really depends on what the end goal was.至于接下来要做什么,这实际上取决于最终目标是什么。 The simple way to fix this would be, as pointed out in comments here, to simply rename the variables.解决这个问题的简单方法是,正如这里的评论中所指出的,简单地重命名变量。 However, that still wouldn't fix the main issue of trying to access the variable by property name instead of by variable name.但是,这仍然无法解决尝试通过属性名称而不是通过变量名称访问变量的主要问题。 In order to access a variable by name, simply use its name (and differentiate the names if they share scope), as opposed to trying to access the property name which in this case doesn't exist.为了按名称访问变量,只需使用其名称(并区分名称,如果它们共享范围),而不是尝试访问在这种情况下不存在的属性名称。

Since it hasn't been mentioned here yet, I will add another possible way to do this by leveraging this and scope by calling the functions with .apply() , like so:由于这里还没有提到它,我将添加另一种可能的方法,通过使用.apply()调用函数来利用this和作用域,如下所示:

 var x = 10; function outer() { var x = 20; function inner() { var x = 30; function printX() { // this now contains all 3 x variables without adding any parameters to any of the functions console.log("Window x:", this.windowX); console.log("Outer x:", this.outerX); console.log("Inner x:", this.innerX); } // pass through existing context (which we got from inner.apply(...) down below, as well as add // inner() x value to the new context we pass to printX() printX.apply({...this, innerX: x}); } // pass through existing context (which we got from outer.apply(...) down below, as well as add // outer() x value to the new context we pass to inner() inner.apply({...this, outerX: x}); } // pass through window level x as "this" to outer(). Technically it's still available via window.x, // but this will be consistent with the others outer.apply({windowX: x});

You are not creating an object attribute but internal variables.您不是在创建对象属性,而是在创建内部变量。 Which you also shadow (that is that you define another with the same name in an inner scope) so that you cannot reach them.您还隐藏了它(即您在内部作用域中定义了另一个具有相同名称的对象),以便您无法访问它们。

Basically you can access outer.x but you have not set it (only a function scoped variable named x).基本上你可以访问outer.x,但你没有设置它(只有一个名为x的函数范围变量)。 And to answer your question "if you can get to that variable": No sorry.并回答你的问题“如果你能得到那个变量”:不抱歉。 since you have shadowed it by defining an inner variable with the same name.因为你通过定义一个同名的内部变量来隐藏它。

What you could do is this:你可以做的是:

var x = 10;
function outer() {
    outer.x = 20;
    function inner() {
        inner.x = 30;
        function printX() {
            console.log(outer.x);
        }
        printX();
    }
    inner();
}
outer();

but that would just make the other variables useless, and also setting variables on functions just because you can is not the best practice.但这只会使其他变量无用,并且仅仅因为您可以在函数上设置变量并不是最佳实践。

Keep learning.保持学习。

You can take a look at the concept of scope to get more clarity, but the first x is in the global scope and can be accessed within the function, but you reassigned the variable value to be 20 within the outer function.您可以查看范围的概念以获得更清晰的信息,但是第一个 x 在全局范围内并且可以在函数内访问,但是您在外部函数内将变量值重新分配为 20。 If you console log the value of x within the outer function, but not inside the inner function, the result will be 20. You assigned the value 30 to x in the inner function, so when you access x within the inner function, it will be 30. If you console.log(x) in each location, you will see the different results.如果在外部函数中控制台记录 x 的值,而不是在内部函数内部,则结果将为 20。您在内部函数中将值 30 分配给 x,因此当您在内部函数中访问 x 时,它将是30。如果你在每个位置console.log(x),你会看到不同的结果。

var x = 10;

function outer() {
    var x = 20;

function inner() {
    var x = 30;

    function printX() {
        console.log(x);
    }

    printX();
}

inner();
console.log(x);

} }

outer();外(); console.log(x);控制台日志(x);

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

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