javascript - 如何在 Javascript 中使用带函数表达式的变量提升?
问题描述
我知道变量提升是将声明移动到函数或全局上下文顶部的行为。这显示在下面的代码中:
console.log(a);
var a = 'Hello World!';
上面的代码实际上得到了以下行为:
var a;
console.log(a);
a = 'Hello World!';
上述代码的结果输出是undefined
.
在上面的示例中,重要的是要注意变量提升仅移动顶部的声明部分。初始化部分没有移到顶部。
当我尝试使用函数表达式复制相同的行为时,我得到了一个意外的输出。
这显示在下面的代码中:
function sayHello() {
var say = function() { console.log(hello); }
var hello= 'Hello World !!';
return say;
}
sayHello()(); // output Hello World !!
我试图理解为什么我们没有收到undefined
输出,因为该变量hello
仅在使用后才被初始化(类似于前面的示例)。
解决方案
您看到的行为来自闭包的工作方式。并不是说 的值以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()
在该行之前插入 a 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
被创建并分配了一个带有 body 的函数表达式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
变量。
推荐阅读
- django-admin - 使用 Django-import-export 在 Django Admin 中导入行后,如何获取 Id?
- laravel - 测试期间的 Laravel 模拟策略
- javascript - HighStock Depthchart 正在奇怪地更新数据
- coq - 为什么嵌套归纳策略也将归纳假设嵌套在 lambda 下?
- node.js - 定向多导线
- python - hashlib.sha256(hashlib.sha256(str(x).encode()).digest()).hexdigest() 可以有多少个值?
- javascript - 在边界外单击时触发带有 onclick 事件的自定义元素
- java - 如何手动更新/评估使用“自定义”公式的单元格?
- snakeyaml - 如何在 SnakeYaml 中“呈现”?
- php - 如何将数组转换为csv