Javascript 函数作用域和提升

IT技术 javascript scope scoping hoisting
2021-02-03 20:14:25

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

var a = 1;

function b() {
    a = 10;
    return;

    function a() {}
}
b();
alert(a);

使用上面的代码,浏览器会提示“1”。

我仍然不确定为什么它返回“1”。他说的一些事情浮现在脑海中:所有的函数声明都被提升到顶部。您可以使用函数作用域变量。仍然没有为我点击。

6个回答

函数提升意味着函数被移动到其作用域的顶部。那是,

function b() {  
   a = 10;  
   return;  
   function a() {} 
} 

将由 interpeter 重写为此

function b() {
  function a() {}
  a = 10;
  return;
}

很奇怪吧?

此外,在这种情况下,

function a() {}

表现与

var a = function () {};

所以,本质上,这就是代码所做的:

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"
函数体绝不是“重写”的。各种 ECMAScript 标准明确规定在代码执行开始之前处理变量和函数声明。也就是说,没有移动,它是关于执行顺序的(因此我不喜欢术语“提升”,它推断移动或重新排列)。在你重新编写的代码中,声明var a应该在函数声明之前,赋值a = 1应该在之后。但请注意,解析器、标记器、解释器、编译器等并未指定这实际上发生,它只是等效的。
2021-03-13 20:14:25
“此外,在这种情况下,function a() {}表现一样var a = function () {}; -这是在两个方面不正确的:第一,如果有的话,它会一直var a = function a() {};(函数实际上不是匿名的),第二,这两种形式是不能互换的,因为从var a = function a() {};只有var a;一部分会被吊起。a = function a() {};部分仍然在 return 语句后面。因为原始形式是一个函数声明而不是一个函数表达式,所以它实际上是作为一个整体提升的。
2021-03-21 20:14:25
@dev.e.loper 是的,在 Javascript 中,函数是一流的对象,就像字符串和数字一样。这意味着它们被定义为变量,可以传递给其他函数,存储在数组中,等等。
2021-03-24 20:14:25
那么所有的函数声明最终都分配给了一个变量?
2021-04-02 20:14:25
@RobG 当然,我想您可以将描述称为“对儿童的小谎言”,但最终行为是相同的,无论是从字面上重新排列代码还是仅重新排列执行顺序。幕后实际发生的事情更多是学术上的关注,甚至可能取决于实现。
2021-04-04 20:14:25

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

function a() {} 

真的变成

var a = function () {}

var a 强制它进入局部作用域,而变量作用域是贯穿整个函数的,所以全局 a 变量仍然是 1,因为你已经通过将 a 声明为一个函数而进入局部作用域。

该函数a在函数内部被提升b

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

这几乎就像使用var

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

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

这行 "var a = function () {}; " 使一切都清楚.. 基本上 JavaScript 是动态语言,而 "function" 也是 JavaScript 中的一个对象。
2021-03-11 20:14:25
  1. 函数声明function a(){}首先被提升,它的行为类似于var a = function () {};,因此在本地范围内a被创建。
  2. 如果你有两个同名的变量(一个在全局另一个在本地),局部变量总是优先于全局变量。
  3. 设置时a=10,您设置的是局部变量a,而不是全局变量

因此,全局变量的值保持不变,您会收到警报 1

function a() { }是一个函数语句,它创建一个函数a局部变量b
解析函数时会创建变量,而不管varor 函数语句是否被执行。

a = 10 设置这个局部变量。

@Sean:不,因为函数语句创建了一个本地标识符。
2021-03-10 20:14:25
除非您添加(在支持该指令的环境中),否则执行函数时实际上会a = 10全局范围内设置一个变量b"use strict"
2021-03-25 20:14:25
......而且......你是对的。没有意识到函数提升的特殊后果。谢谢!
2021-03-25 20:14:25