从JavaScript预编译看function的生存时间
今天做Ajax发现一个现象:Ajax部分刷新后,新生成的页面仍然能够调用刷新前页面的function。上网搜集资料后发现,该现象与JS的预编译有关。
--Brisk Yu
<script> var a = 1; function b() { alert(a); var a = 2; alert(a); } b(); </script>
观察以上JS代码,输出的结果是 undefined 和 2, 而不是 1 和 2。
1)当JS执行到<script>标签时会首先进入“预编译”阶段。此时解释器会:
1 寻找var,将其作为window的属性,并赋值undefined;
2 寻找function,将其作为window的属性,并将方法体赋值给它。
因此此时window对象看起来像是这样:
window = { //document等属性。。。 a:undefined, b:function b() { alert(a); var a = 2; alert(a); } }
2)此时开始逐行执行JS代码,执行完var a=1;后,window对象中的属性值被更新:
window = { //document等属性。。。 a:1, b:function b() { alert(a); var a = 2; alert(a); } }
3)接下来执行代码b(); 此时进入方法体后会再次进行预编译,即寻找var 和 function关键字。
此时会创建活动对象AO(Active Object)[2]:
在一个函数对象被调用的时候,会创建一个活动对象,首先将该函数的每个形参和实参,都添加为该活动对象的属性和值;将该函数体内显示声明的变量和函数,也添加为该活动的的属性(在刚进入该函数执行环境时,未赋值,所以值为undefined,这个是JS的提前声明机制)[1]。
此时function b的AO形如:
AO = { //arguments等属性。。。 a:undefined }
4)逐步执行function b 中的代码。执行第一个alert时a:undefined,执行第二个alert时a:2。
5)综上所述,页面加载时,JS的预编译将var 和 function添加到了window对象作为其的属性。因此当Ajax部分刷新页面时,window对象的属性并没有变,所以新页面仍然能调用其方法。(我认为:JS执行方法不是到代码中去找方法体,而是去window对象中找是否有相关属性,其属性值即为方法体)
参考资料:
[1] https://www.cnblogs.com/amy-fox/p/5856771.html
[2] https://blog.csdn.net/q1056843325/article/details/52951114