2016-10-27 20 views
1

看着从这个site吊装例子,我不知道为什么下面变造1甚至悬挂后:空函数声明如何在JavaScript中使用吊装工作?

var a = 1; 
function b() { 
    a = 10; 
    return; 
    function a() {} 
} 
b(); 
alert(a); // alerts 1 

实际上是

var a = 1; 
function b() { 
    function a() {} 
    a = 10; 
    return; 
} 
b(); 
alert(a); 

难道不应该改变10,因为ab函数返回之前还是分配给10个?为什么调用一个空的函数会导致这个问题?在一个相关的说明中,为什么下面没有提示功能,但仍然改变1? a不会被重新分配给声明的函数吗?

var a = 1; 
function a() {} 
alert(a); 
+1

'功能(){}'就像' var a;'。 'b'中的'a'不是外面的'a'。另外'a'永远不会被调用。 – Xufox

+0

'函数a(){}'将为函数创建一个指针并且'a = 10'将赋值给这个指针,而不是定义在外的'a' – Rajesh

+0

您的第一个代码片段* * *实际上被解析为第二个一。 'a'变量总是超出函数a()'的范围。 – haim770

回答

4

让我们把它一行一行,

在这里,b();调用该函数bb在它的正文中有什么功能?声明一个名为a的新函数。当您在b内部访问a时,实际上不会访问全局变量a,而是您刚刚声明的函数。因此,10将被设置为指向函数的指针,称为a而不是全局变量,称为a

但是为什么第一个代码块会提醒1?我很困惑

因为当JavaScript引擎去执行任务:其中a已经定义

a = 10; 

检查。由于在当前范围中,您尝试将其设置为10到a,因此存在函数声明,其名称为a,那么将发生上述情况。但你会说为什么?函数声明位于赋值之下。发生这种情况的原因是JavaScript引擎首先处理脚本中的声明,然后继续执行脚本。所以当发动机质疑a,其中a被定义时,它会一如既往地首先查看当前范围。如果不存在,那么它将查看当前作用域所在的作用域。在你的情况下,这是全局范围,正如我从你的代码中可以推断出的那样。所以如果你没有定义这个函数,我之前提到的第二步就已经完成了,因为有一个叫做a的变量,它会改变它的值。如果没有那么a就已经在全球范围内定义一个变量,它的价值将是10

var a = 1; 
 
function b() { 
 
    a = 10; 
 
    return; 
 
    // I renamed the function from a to c to notice the hoisting 
 
    function c() {} 
 
} 
 
b(); 
 
console.log(a);

+0

但为什么第一块代码会提醒1?我很困惑 –

+0

@Reddy _“[Y]你实际上不访问全局变量'a'”_。 – Xufox

+0

@Xufox但是'a = 10;'会访问全局定义的'a'权限? –