如何在Javascript中使用带函数表达式的变量?
我理解变量提升是将声明移动到函数或全局上下文顶部的行为。 代码如下所示:如何在Javascript中使用带函数表达式的变量?,javascript,function,hoisting,Javascript,Function,Hoisting,我理解变量提升是将声明移动到函数或全局上下文顶部的行为。 代码如下所示: console.log(a); var a = 'Hello World!'; function sayHello() { var say = function() { console.log(hello); } var hello= 'Hello World !!'; return say; } sayHello()(); // output Hello World !! 上述代码实际上获得以
console.log(a);
var a = 'Hello World!';
function sayHello() {
var say = function() { console.log(hello); }
var hello= 'Hello World !!';
return say;
}
sayHello()(); // output Hello World !!
上述代码实际上获得以下行为:
var a;
console.log(a);
a = 'Hello World!';
上述代码的结果输出为未定义
在上面的示例中,需要注意的是,变量提升仅移动顶部的声明部分。初始化部分不会在顶部移动
当我试图使用函数表达式复制相同的行为时,我得到了一个意外的输出
如下代码所示:
console.log(a);
var a = 'Hello World!';
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)部分)仅在设置值后执行
为了避免与吊装混淆,因为这与您所看到的并不相关,让我们以吊装后的方式编写代码:
函数sayHello(){
你好;
var say=function(){console.log(hello);}
你好=‘你好,世界!!’;
还说;
}
sayHello()();//输出你好世界!!
如果您想在hello='hello World!!'行之前插入一个say()
代码>它将打印未定义的
现在,当你有这样的代码
var你好;
var say=function(){console.log(hello);}
…那么hello
内部say
不是外部hello
的副本,它实际上是您在这里引用的同一个变量。即使在外部函数返回后,它仍然存在,因为现在您有了对say
函数的引用,而该函数反过来仍然保留了对hello
的引用
我试图理解为什么我们没有将undefined
作为输出接收,因为变量hello
只有在使用后才会初始化(类似于前面的示例)
我想这是你的误解。当您在最末尾调用say
函数时使用它-按时间顺序说。事实上,从上到下查看代码时,hello
之前似乎是“使用过”的,这并不重要,因为这不是代码执行的顺序。在var say=function(){console.log(hello);}
行中,您只需执行var say=something
,某物
在这一点上没有任何意义(它只需要语法正确)。只有当您在末尾调用say
时,才能访问hello
(您也可以尝试使用类似var say=function(){derp();}
,您会注意到,只有在调用该函数时,而不是在定义该函数时,才会出现错误derp未定义
)
因此,按时间顺序,发生的情况如下:
- 调用
sayHello
已创建并包含hello
未定义的
创建并分配了一个函数表达式,其中包含bodysay
console.log(hello)
被指定为hello
“hello World!!”
返回sayHello
say
- 调用函数表达式(即
)say
执行console.log(hello)
- 记住,
在那一点上包含了hello
“hello World!!”
- 记住,
- 字符串
将被打印出来“Hello World!!”
函数sayHello(){
你好;
var say=function(){console.log(hello);}
你好=‘你好,世界!!’;
var think=function(){hello='我应该考虑什么?';}
回报[说,想];
}
var[say,think]=sayHello();
说()打印“你好,世界!!”;
思考();
说()打印“我该怎么想?”
如您所见,
hello
仍然存在,并且可以被say
和think
使用,即使在sayHello
返回后,代码的所有这些部分都引用相同的hello
变量。您看到的行为来自闭包的工作方式。并不是因为hello
的值以某种方式被提升,而是读取hello
的值的代码(console.log(hello)部分)仅在设置值后执行
为了避免与吊装混淆,因为这与您所看到的并不相关,让我们以吊装后的方式编写代码:
函数sayHello(){
你好;
var say=function(){console.log(hello);}
你好=‘你好,世界!!’;
还说;
}
sayHello()();//输出你好世界!!
如果您想在hello='hello World!!'行之前插入一个say()
代码>它将打印未定义的
现在,当你有这样的代码
var你好;
var say=function(){console.log(hello);}
…那么hello
内部say
不是外部hello
的副本,它实际上是您在这里引用的同一个变量。即使在外部函数返回后,它仍然存在,因为现在您有了对say
函数的引用,而该函数反过来仍然保留了对hello
的引用
我试图理解为什么我们没有收到未定义的作为输出,因为变量hello
已初始化