Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/409.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Javascript中使用带函数表达式的变量?_Javascript_Function_Hoisting - Fatal编程技术网

如何在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
    已创建并包含
    未定义的
  • say
    创建并分配了一个函数表达式,其中包含body
    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
已初始化