块级作用域中的函数声明

本文探讨了JavaScript中函数声明在预编译时的提升行为,区分了块级和局部作用域的影响,解释了为什么块级作用域中的函数声明会提升到全局并赋值为`undefined`,而局部函数仅限于其作用域。通过实例演示了不同作用域下变量值的变化过程和断点调试的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

{  
	console.log(window.a,a)   //全局 undefined   局部 fn
	a = 2;
	console.log(window.a,a)   //全局 undefined   局部 2
	a = 3;
	console.log(window.a,a)   //全局 undefined   局部 2
	function a(){}           //执行完之后全局变为3 函数声明之后将全局变量赋值为函数声明之前的局部变量值
				
	console.log(window.a===a,a) //全局 3   局部 3
	a = 4;  
	console.log(window.a,a); //全局3  局部4
}
	console.log(window.a,a); //全局 3
  •   预编译时,将块级作用域中的函数声明同时提升到全局和块内顶部,但块内顶部的赋值为function a(){}  ,全局的赋值为undefined
  •   a = 2,a = 3 都改的块级中的 a,执行完 a = 3 时块内中的a变为3,全局中的不变;
  •   块内执行到函数声明时,由于函数不具备块级作用域,会将全局中的a改为块内中的a,即,window.a = 3;
  •   后面执行a = 4时,会顺着作用域链往上找,由于块级中已经有a了,因此会将块级中的a的改为4,局部不变;
  •   块级作用域中执行到函数声明时会将a提升到全局,没有执行函数声明之前提升到块级顶部; 
  • {
    	function a(){};
    }
    console.log(a); //会输出function a(){}
  •  但在局部作用域(函数内)中函数声明不会提升到全局中,只能在局部作用域顶部;
  • function b(){
        function a(){};
    }
    console.log(a); //报错

块级作用域中函数声明可以打断点,但在局部作用域中不能打断点,也就是说在块级作用域中函数声明会执行,但在局部作用域中函数声明,只做声明,本身自身不执行

块级:块级作用域中的函数在预编译的时候会被提升到全局中单赋值为undefined,只有在执行到函数声明时才是赋值,

此时全局并未定义a,但是可以在全局中看见有a=undefined,说明预编译时已将块内的函数提上来但赋值为undefined,执行完函数声明之后a = 3,将全局中的a改为3

注释函数声明之后,预编译时全局中就不会出现a

 

函数函数内的函数声明不会提升到全局中

将块换为函数之后,全局中就不会出现a 

### JavaScript 中函数作用域与块级作用域 #### 函数作用域特性 在JavaScript中,当变量被定义在一个函数内时,则该变量具有函数作用域。这意味着此变量仅能在其所在的函数内部访问,在外部则无法获取到这个变量的信息[^1]。 ```javascript function exampleFunction() { var functionScopedVariable = "I'm scoped to this function"; console.log(functionScopedVariable); // 输出: I'm scoped to this function } console.log(functionScopedVariable); // 抛出错误, 变量未定义 exampleFunction(); ``` #### 块级作用域特性 自ES6起引入了`let`和`const`关键字用于创建拥有块级作用域的变量。这种类型的变量只存在于由花括号界定的一段代码之内——比如if语句或for循环体内;一旦离开这段区域就不再可见[^5]。 ```javascript { let blockScopedVariable = 'I exist only within these curly braces'; const alsoBlockScoped = true; } // 尝试在此处打印上述两个变量会抛错,因为已经超出了它们的作用域边界 ``` #### 主要区别 - **生命周期**: 对于使用`var`声明的变量来说,即使是在条件判断或者循环结构里初始化,仍然会在整个封闭函数范围内有效甚至在整个文件(如果是顶层)下都存在。而采用`let`/`const`的方式能够更精确控制变量的存在周期,限制在特定的代码区块之中。 - **重复声明处理**: 如果尝试在同一作用域多次声明同一个名字的`var`型变量是可以接受的行为,但是这样做对于`let`和`const`就会引发语法错误,除非这些声明位于不同的嵌套层次上[^4]。 #### 实际应用案例对比 下面的例子展示了两种不同方式下的行为差异: ```javascript // 函数作用域例子 for (var i = 0; i < 3; i++) {} console.log(i); // 输出: 3 // 块级作用域例子 for (let j = 0; j < 3; j++) {} console.log(j); // ReferenceError: j is not defined ``` 在这个简单的迭代过程中可以看到,由于`i`是通过`var`声明并处于函数级别作用域之下,所以在循环结束后依旧可以在外面找到它;相反的是,利用`let`建立起来的`j`遵循着严格的块级规则,因此超出它的限定范围之后便不可再触及。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值