Вложенные функции имеют доступ к области над ними, но имеет ли значение, где они были определены?

Я всегда думал, что вложенные вызовы функций имеют доступ к области над ними независимо от того, где функция была определена (в приведенном ниже примере я думал, что функция printsomething будет иметь доступ к "что-то" в функции runeverything). Согласно приведенной ниже скрипке, это не так. Должна ли функция printsomething быть определена (а не просто вызвана) во внешней функции runeverything, чтобы иметь доступ к локальным переменным, определенным в другой функции runeverything?

Это важно для меня сейчас, потому что модули узлов поднимаются наверх, когда они импортируются. Это создает проблемы для меня!

function foo(){
function printsomething() {
  $('#test').text(something || 'nothing');
};
  
var something = 'something';

function runeverything() {
  
  printsomething(); //returns "something is not defined"
}

runeverything();
};

foo();
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1 id="test"></h1>


person mags    schedule 17.06.2016    source источник
comment
Какой вопрос? То, что вы нашли в своем тесте, верно: JavaScript имеет статическую лексическую область видимости. Точка в коде, в которой объявляется функция, определенно имеет значение.   -  person Pointy    schedule 17.06.2016
comment
Что я могу сделать в узле, когда импорт модуля поднимается наверх? Когда я вызываю метод из модуля, я должен передать все переменные как параметры, потому что метод не может получить доступ к переменным внешней функции. Есть ли какое-то решение для этого?   -  person mags    schedule 17.06.2016
comment
Опять же, JavaScript имеет статическую лексическую область видимости. Для этого нет решения - это фундаментальная природа языка.   -  person Pointy    schedule 17.06.2016


Ответы (2)


Для этого вам нужно, чтобы эти функции были встроены в другую функцию: т.е.:

function foo() {
    function printsomething() {
        $('#test').text(something || 'nothing');
    };

    function runeverything() {
        printsomething(); //returns "something"
    }

    var something = 'something';
    runeverything();
};
foo();

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

person Mayday    schedule 17.06.2016
comment
Я отредактировал свой фрагмент выше. Попробуйте запустить его. Внешняя функция foo не решает проблему. Я тоже так думал, и это меня очень смутило. - person mags; 17.06.2016
comment
У вас все еще есть переменная, определенная в функции runeverything. вам нужно определить его в функции foo - person Mayday; 17.06.2016
comment
О, ты прав. Виноват. Спасибо, что поймали это. К сожалению, похоже, что код, который я импортирую в узел через require, всегда поднимается на самый верх над любой внешней функцией! В контексте, в котором я работаю, к сожалению, это не сработает, но вы все равно получите голосование, потому что это полностью отвечает на вопрос, который я задал. - person mags; 17.06.2016
comment
почему бы вам не создать один объект со всеми переменными в качестве свойств объекта и передать этот объект только при вызове функций? то есть var obj={var1: 'abc',var2:'def'}; вызывать функцию (объект) - person Mayday; 17.06.2016
comment
Да, я надеялся, что мне не придется этого делать :) - person mags; 17.06.2016

Да.

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

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

person Quentin    schedule 17.06.2016
comment
Спасибо. Я устал передавать огромные объекты параметров, когда я вызываю функции из других модулей в узле (функции из других скриптов, которые мне нужны). Есть ли у вас опыт решения этой проблемы? - person mags; 17.06.2016