簡體   English   中英

如何從 JavaScript 的外部作用域訪問變量

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

在下面的示例中,我試圖訪問函數外層中的x

我期望得到 20 作為輸出,但是輸出是undefined

有人可以解釋為什么會發生這種情況,有沒有辦法訪問外部 x?

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

作用域在 JavaScript 中不是這樣設計的。 為了將變量 x 附加到其作用域,您需要通過名稱或通過此引用來引用該作用域的對象。

您的示例中發生的情況是您對 printX 的調用嘗試記錄附加到函數外部的變量 x 。 函數從 JavaScript 中的對象派生,因此它們可能具有附加到它們的屬性,因此不是給您一個引用錯誤,而是您得到 undefined,因為變量不存在。

有關作用域的更多信息,請參閱我對 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();

至於接下來要做什么,這實際上取決於最終目標是什么。 解決這個問題的簡單方法是,正如這里的評論中所指出的,簡單地重命名變量。 但是,這仍然無法解決嘗試通過屬性名稱而不是通過變量名稱訪問變量的主要問題。 為了按名稱訪問變量,只需使用其名稱(並區分名稱,如果它們共享范圍),而不是嘗試訪問在這種情況下不存在的屬性名稱。

由於這里還沒有提到它,我將添加另一種可能的方法,通過使用.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});

您不是在創建對象屬性,而是在創建內部變量。 您還隱藏了它(即您在內部作用域中定義了另一個具有相同名稱的對象),以便您無法訪問它們。

基本上你可以訪問outer.x,但你沒有設置它(只有一個名為x的函數范圍變量)。 並回答你的問題“如果你能得到那個變量”:不抱歉。 因為你通過定義一個同名的內部變量來隱藏它。

你可以做的是:

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

但這只會使其他變量無用,並且僅僅因為您可以在函數上設置變量並不是最佳實踐。

保持學習。

您可以查看范圍的概念以獲得更清晰的信息,但是第一個 x 在全局范圍內並且可以在函數內訪問,但是您在外部函數內將變量值重新分配為 20。 如果在外部函數中控制台記錄 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);

}

外(); 控制台日志(x);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM