Как получить доступ к переменной из внешней области видимости в JavaScript - PullRequest
0 голосов
/ 07 сентября 2018

В приведенном ниже примере я пытаюсь получить доступ к x, который находится в функции external.

Я ожидал получить 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();

Ответы [ 4 ]

0 голосов
/ 07 сентября 2018

Вы можете взглянуть на концепцию scope , чтобы получить больше ясности, но первый 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);

}

наружная (); console.log (х);

0 голосов
/ 07 сентября 2018

Сферы не спроектированы таким образом в JavaScript. Чтобы присоединить переменную x к ее области действия, вам нужно будет ссылаться на объект для этой области либо по имени, либо по этой ссылке.

В вашем примере происходит то, что ваш вызов printX пытается записать переменную x, присоединенную к функции external. функции наследуются от объектов в 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();

Что касается того, что делать дальше, это действительно зависит от конечной цели. Как было указано в комментариях, простой способ исправить это - просто переименовать переменные. Однако это все равно не решит основную проблему при попытке доступа к переменной по имени свойства, а не по имени переменной. Чтобы получить доступ к переменной по имени, просто используйте ее имя (и различайте имена, если они разделяют область видимости), а не пытайтесь получить доступ к имени свойства, которого в этом случае не существует.

0 голосов
/ 07 сентября 2018

Поскольку это еще не было упомянуто здесь, я добавлю еще один возможный способ сделать это, используя this и видимость, вызывая функции с .apply(), например, так:

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});
0 голосов
/ 07 сентября 2018

Вы создаете не атрибут объекта, а внутренние переменные. От которого вы также скрываете (то есть определяете другого с таким же именем во внутренней области видимости), чтобы вы не могли достичь его.

По сути, вы можете получить доступ к 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();

но это просто сделает другие переменные бесполезными, а также установит переменные для функций только потому, что вы можете это не лучшая практика.

Продолжай учиться.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...