Поведение, которое вы видите, происходит от того, как работают замыкания. Дело не в том, что значение hello
каким-то образом поднимается, а в том, что код, который читает значение hello
(часть console.log(hello)
), выполняется только после того, как вы установите значение!
Чтобы не получить перепутать здесь с подъемом, так как это на самом деле не имеет отношения к тому, что вы видите, давайте выпишем код так, как он будет выглядеть после подъема:
function sayHello() {
var hello;
var say = function() { console.log(hello); }
hello = 'Hello World !!';
return say;
}
sayHello()(); // output Hello World !!
Если вы вставите say()
перед строка hello = 'Hello World !!';
будет печатать undefined
.
Теперь, когда у вас есть такой код ...
var hello;
var say = function() { console.log(hello); }
... тогда hello
внутри say
не является копией внешней hello
, на самом деле это та же переменная, на которую вы ссылаетесь здесь. И он продолжает существовать даже после возвращения внешнего функционала, потому что теперь у вас есть ссылка на функцию say
, которая в свою очередь сохраняет ссылку на hello
.
Я пытаюсь понять, почему мы не получили undefined
в качестве вывода, потому что переменная hello
инициализируется только после ее использования (аналогично предыдущему примеру).
Я думаю, что это ваше недоразумение. Используется, когда вы вызываете функцию say
в самом конце - в хронологическом порядке. Тот факт, что взгляд на код сверху вниз hello
кажется «использованным» ранее, не имеет значения, потому что это не тот порядок, в котором выполняется код. В строке var say = function () { console.log(hello); }
вы просто делаете var say = something;
, something
не имеет никакого значения в этой точке (это просто должно быть синтаксически правильным). Доступ к hello
происходит только при вызове say
в конце.
(Вы также можете попробовать что-то вроде var say = function () { derp(); }
, и вы заметите, что получаете только ошибку derp is not defined
когда вы вызываете эту функцию, а не когда вы ее определяете.)
Итак, в хронологическом порядке происходит следующее:
sayHello
называется hello
создан и содержит undefined
say
создан и ему назначено выражение функции с телом console.log(hello)
hello
назначено "Hello World !!"
sayHello
возвращает say
- Выражение функции (которое было
say
) называется console.log(hello)
выполняется - Помните, что
hello
содержит "Hello World !!"
в эта точка
- Будет напечатана строка
"Hello World !!"
Вы можете расширить этот пример, чтобы лучше понять:
function sayHello() {
var hello;
var say = function() { console.log(hello); }
hello = 'Hello World !!';
var think = function() { hello = 'What should I think about?'; }
return [say, think];
}
var [say, think] = sayHello();
say(); // Prints "Hello World !!";
think();
say(); // prints "What should I think about?"
Как Вы можете видеть, что hello
просто живет и может использоваться как say
, так и think
, даже после возврата sayHello
, все эти части кода ссылаются на одну и ту же hello
varia. BLE.