Javascript函数范围和提升

dev*_*per 85 javascript scope scoping hoisting

我刚刚阅读了一篇关于Ben Cherry的JavaScript范围和提升的精彩文章,其中他给出了以下示例:

var a = 1;

function b() {
    a = 10;
    return;

    function a() {}
}
b();
alert(a);
Run Code Online (Sandbox Code Playgroud)

使用上面的代码,浏览器将发出"1"警报.

我仍然不确定它为什么会返回"1".他说的一些事情就像是:所有的功能声明都被提升到顶部.您可以使用函数来调整变量的范围.仍然没有为我点击.

Pet*_*son 112

功能提升意味着功能被移动到其范围的顶部.那是,

function b() {  
   a = 10;  
   return;  
   function a() {} 
} 
Run Code Online (Sandbox Code Playgroud)

将被重复者重写为此

function b() {
  function a() {}
  a = 10;
  return;
}
Run Code Online (Sandbox Code Playgroud)

很奇怪,是吗?

此外,在这种情况下,

function a() {}
Run Code Online (Sandbox Code Playgroud)

表现得一样

var a = function () {};
Run Code Online (Sandbox Code Playgroud)

所以,从本质上讲,这就是代码所做的事情:

var a = 1;                 //defines "a" in global scope
function b() {  
   var a = function () {}; //defines "a" in local scope 
   a = 10;                 //overwrites local variable "a"
   return;      
}       
b();       
alert(a);                 //alerts global variable "a"
Run Code Online (Sandbox Code Playgroud)

  • @ dev.e.loper是的,在Javascript中,函数是第一类对象,就像字符串和数字一样.这意味着它们被定义为变量,可以传递给其他函数,存储在数组中,等等. (14认同)
  • _"此外,在这个例子中,`function a(){}`的行为与`var a = function(){};``_ - 这两种方式不正确:首先,如果有的话,它会'是`var a = function a(){};`(函数实际上不是匿名的),其次,这两种形式是不可互换的,因为来自`var a = function a(){};`只有`var a ;'部分将被悬挂.`a = function a(){};`部分仍然在return语句后面.因为原始表单是函数声明而不是函数表达式,所以它实际上是作为一个整体提升的. (5认同)
  • 功能体绝不"重写".各种ECMAScript标准明确规定在代码执行开始之前处理变量和函数声明.也就是说,**没有任何动静**,它是关于执行的顺序(因此我不喜欢"提升"这个词,它推断出运动或重新排列).在你重写的代码中,声明`var a`应该在函数声明之前,并且赋值`a = 1`应该在之后.但请注意**解析器,令牌器,解释器,编译器等没有指定实际发生**,它只是一个等价物. (3认同)
  • @RobG当然,我猜你可以把这个描述称为小"[骗孩子"](https://en.wikipedia.org/wiki/Lie-to-children),但最后行为是一样的,代码是字面上重新排列还是重新排列执行顺序.幕后实际发生的事情更多是学术上的关注,甚至可能依赖于实现. (3认同)
  • 所有函数声明最终都分配给一个变量? (2认同)

kem*_*002 6

你必须要记住的是它解析整个函数并在执行之前解析所有变量声明.所以....

function a() {} 
Run Code Online (Sandbox Code Playgroud)

真的变成了

var a = function () {}
Run Code Online (Sandbox Code Playgroud)

var a 强制它进入局部范围,变量范围是通过整个函数,因此全局变量仍然是1,因为你已经通过使它成为一个函数而声明了一个局部范围.


Dig*_*ane 5

函数a内部悬挂功能b:

var a = 1; 
function b() { 
   function a() {} 
   a = 10; 
   return;
} 
b(); 
alert(a);
Run Code Online (Sandbox Code Playgroud)

这几乎就像使用var:

var a = 1; 
function b() { 
   var a = function () {};
   a = 10; 
   return;
} 
b(); 
alert(a);
Run Code Online (Sandbox Code Playgroud)

该函数在本地声明,并且a只在本地范围内进行设置,而不是全局变量.