JavaScript预解析与变量提升机制详解
本文深入解析JavaScript引擎在执行代码前的预解析机制,详细对比var变量声明与function函数声明在提升行为上的差异。通过具体代码示例,阐明函数声明优先级高于变量声明的原理,以及重复声明和赋值覆盖对最终结果的影响,帮助开发者理解JS执行上下文的关键细节。
什么是预解析?
概念:
在JavaScript代码正式从上往下执行之前,浏览器引擎会先对代码进行一次扫描解析,将所有变量声明提取出来,这一过程被称为预解析。
详讲
预解析的核心逻辑是:查找当前作用域内的 和 声明(注意:匿名函数没有函数声明,因此不会发生提升),预先进行声明处理,而将赋值操作保留在代码原本的位置,随后再按顺序执行代码。这就是预解析的完整过程。
变量和函数预解析的区别
在预解析阶段,所有使用 var 声明的变量,以及使用 function 声明的函数,都会被提升到其所在作用域的顶端。
对于 var 声明的变量,在预解析时仅提前声明,赋值语句依然保留在代码原位置执行。
对于 function 声明的函数,在预解析时不仅提前声明,还会同时完成定义。而在函数实际执行时,函数内部才会再次进行预解析。
注意: 匿名函数没有function声明,所以不会提升
重复声明var变量
var重复声明时:若已经存在,编译器会忽略 var 继续向下编译;
若该变量不存在,则顺着作用域链向上查找,
若在整个作用域链中都没有找到,则会在当前作用域内声明该变量。
变量提升和函数提升优先级
总结:
函数提升的优先级高于变量提升。同名情况下,函数声明不会被变量声明覆盖,但会被后续的变量赋值操作所覆盖。
下面内容转载自:
https://blog.csdn.net/caoyafeicyf/article/details/53172532
函数优先级大于变量优先级的深入探究
浏览器的预解析过程
先由一道小题进入本文
var foo;
function foo(){}
console.log(foo);
结果是函数体function foo(){}
接着下面一道题:
function foo(){}var foo;console.log(foo);
结果也是函数体
function foo(){}
所有就有很多人说,函数声明的优先级大于变量声明的优先级。
那么,为什么呢?这就要从浏览器的预解析说起了。
预解析流程
搜寻预解析关键字
寻找var关键字
寻找function关键字
执行预解析
先应用var关键字声明的标识符,使这些标识符有定义 标识符有定以后,使用这项标识符就不会报错了但因为没有赋值,因此其值为undefined
至此标识符中保存了函数的引用
几个需要注意的细节
- var 关键字对同一个标识符重复使用时,除第一次有效外,其他均做忽略处理。
- 预解析时先处理变量声明,再处理函数声明不
- 要纠结谁的优先级高,这些只是表面现象
- 懂得了预解析流程,一切都是浮云
看了预解析原理以后,下面咱们回到本文开头的两题,分析下预解析的过程,详细的了解为什么函数的优先级高于变量的优先级。follow me
先看第一个
var foo;
function foo(){}
console.log(foo);
预解析过程为:
var foo;<----变量声明的var
var foo;<----函数声明抽出的var
foo=function (){}<----函数声明抽出的赋值
console.log(foo);
再来看第二个
function foo(){}
var foo;
console.log(foo);
预解析过程为:
var foo;<----变量声明的var
var foo;<----函数声明抽出的var
foo=function (){}<----函数声明抽出的赋值
console.log(foo)
比较这两个,你发现了什么?原来他们的预解析过程一样啊,这也就是为什么函数优先级高于变量的原因了。
如果你理解了上面的内容,那么下面再出一个题:
var a=1;
function a(){}
console.log(a);
这个浏览器是如何解析的呢?下面来跟着我的思路一起走:
1. 解析器首先搜寻var 关键字,结果第一行就发现了,把它提取到开头。
2. 解析器搜寻function关键字,第二行发现了,首先分离var+函数名,此时发现和第一步的一样,不做处理,然后开始分离函数的赋值,也就是a=function (){},此时a为函数体。
3. 解析器接着处理变量的赋值,a=1,上一步的函数体被覆盖掉,此时a=1。
4. 最后处理console.log(a),自然而然的结果为1。
下面是解析器处理的代码过程:
var a;<----变量声明的var
var a;<----函数声明抽出的var
a=function (){}<----函数声明抽出的赋值
a=1;
console.log(a);
以上就是web面试之JS预解析与变量提升区别的详细内容,更多关于JS预解析与变量提升的资料请关注本站其它相关文章!
D3.js 比例尺与坐标轴的配置详解
2026-11-05 16:54:46
JavaScript怎么遍历对象的Symbol键和不可枚举属性
2026-11-05 13:13:39
封装一个健壮的JS字符串判空工具函数
2026-11-05 12:16:14
JavaScript合并数组的三种常用方法:concat、扩展运算符与push
2026-11-05 11:22:29
JavaScript立即执行函数(IIFE)是什么及基本语法
2026-11-05 10:51:19
