JS变量提升与块语句的交互机制及代码疑问解析
JavaScript变量提升与块语句的协同工作原理(附案例解析)
这个问题的核心是理解非严格模式下块级函数的特殊提升规则——这和我们平时熟悉的函数声明提升、var变量提升都有点不一样,咱们一步步拆解你的代码执行过程:
1. 全局作用域的预编译(变量提升)阶段
在代码开始执行前,JS引擎会先扫描整个全局作用域的代码:
- 当它发现块内部的
function abc()时,在非严格模式下,这个函数声明会被提升到全局作用域的顶部,但只完成「变量声明」,不会直接赋值函数体。也就是说,全局作用域里会创建一个abc变量,初始值为undefined。 - 同时,因为全局作用域的变量会挂载到全局对象(也就是这里的
this,浏览器里是window,Node.js里是global)上,所以this对象会新增一个abc属性,值同样是undefined。
这就解释了开头三行的输出:
console.log(this.abc):全局对象上的abc属性存在但值为undefined,所以输出undefinedconsole.log(abc in this):abc已经是全局对象的属性了,所以返回trueconsole.log(abc):全局作用域的abc变量已声明但未赋值,所以输出undefined
2. 块语句的执行阶段
当代码执行到块内部的function abc()时,JS引擎会把这个函数体赋值给之前提升的全局abc变量,同时更新全局对象上的abc属性值为这个函数。
3. 块执行后的阶段
块执行完毕后,全局的abc变量已经被成功赋值为函数体,所以此时console.log(abc)就能输出完整的函数定义了。
补充:严格模式下的差异
如果是在严格模式('use strict')中,块级函数的作用域会被限制在块内部,不会提升到全局作用域。这时候块外部访问abc会直接抛出ReferenceError,和let/const的块级作用域行为一致。
内容的提问来源于stack exchange,提问作者thaveethu gce
相关产品推荐
相关产品推荐

