作用域 - JS解析器如何解析JS代码3

xiaoxiao2021-02-28  95

例1.解析js代码

var a = 1; function fn1(a){//有参数 alert(a);//1 a =2; } fn1(a); alert(a);//1

解析:

第一步、预解析

1、首先读到第一行发现‘var’,于是存储‘a =undefined’; 2、读到第二行发现‘function’,于是存储‘fn1 = function fn1(a){alert(a);var a =2;}’整个函数块都存储下来; 预解析结束。

第二步、逐行解读代码

1、第一行看到a,于是到仓库去找a,然后看到等号,就是表达式,会到仓库去更改值,由‘a=未定义’更改成‘a=1’; 2、第二行看到function函数,就是声明,不能对值进行修改,仓库中a 的值还是1不变。 3、继续读代码看到fn1(a);函数调用,就是让函数里面的代码开始执行。我们知道函数也是一个域,只要是域就会发生域解析,于是函数里面的代码要先进行预解析,再逐行解读代码。如下:①② ①预解析:函数第一行function fn1(a){看到参数a,是要找的关键字,就相当于放着一个空值在这,即函数体的仓库中存放着a = 未定义; 然后继续预解析,看看有没有var、function等没有。 由此局部预解析结束; ②逐行解读代码:第一行看到function fn1(a){,看到参数,因为函数在调用时传参进来,所以函数在调用时直接读取全局变量中a的值a = 1,即function fn1(var a = 1){;(参数是表达式,可以更改局部仓库中的值,所以函数体内仓库中a 的值由‘a = 未定义’改为‘a = 1’)。继续解读代码,读到alert(a);,然后到局部仓库中去寻找a,发现a的值是1,于是弹出1。继续解读代码,读到a =2;于是到局部仓库中寻找a,因为有等号,所以直接把局部仓库中的值改为‘a = 2’; 4、继续解读代码,看到alert(a);,于是到全局仓库中寻找a,弹出1(因为是到外面的大仓库中寻找,不是局部仓库)。

注意:我们可以在函数内部找函数外面的变量,但是不能在函数外面找函数里面的变量。找不到就会直接报错!

想要获取函数内部的变量(怎么获取局部变量)

方法一、可以通过作用域

var str = '';//1、先定义一个空变量 function fn1(){ var a = '鸡腿'; str = a;//2、把空的变量放在函数内部,并把函数体内的变量赋值给该空变量; } fn1(); alert(str);//3、鸡腿

第一步:先定义一个空变量var str = ''; 第二步:把空的变量名放在函数内部,因为在函数解读中局部作用域找不到该变量,会到全局仓库中寻找;(根据作用域链找到父级作用域)然后通过等号,来把函数体内的变量赋值给该变量,这样,函数体内的局部变量值就会到全局变量中; 第三步:在函数体外面访问空变量名str,就会弹出‘鸡腿’;因为此时函数体内的局部变量已经是全局变量了。

方法二、通过函数调用

function fn2(){ var a = '苹果'; fn3(a);//把fn2函数中的局部变量传给fn3函数 } fn2();//函数调用 function fn3(b){ alert(b);//苹果 }

注意:函数的大括号才是一个域,if中的大括号不是一个作用域,同理for的大括号也不是一个作用域。作用域的一个标志是先解析后执行。

如果有if或者for

if(){ var a = 1; } alert(a);

if(){ } var a = 1; alert(a);

效果是一样的,if判断是通透,不会先解析后执行。

注意:不要随便在if、for里面定义变量、函数,如果想定义全局变量、全局函数,那么在if、for外面定义。否则存在兼容性问题(火狐不兼容)。如下,不要这么写:

if(true){ var a = 1; function fn1({ alert(123); } }

最好定义在外面:

if(true){ } var a = 1; function fn1({ alert(123); }

如果函数在for里面

有三个按钮。

var btn = document.getElementsByTagName('input'); for(var i=0;i<btn.length;i++){ btn[i].onclick = function(){ alert(i);//3 } }

上面代码可以简化为:

for(var i=0;i<btn.length;i++){ btn[i].onclick = function(){。。。} }

因为有for所以会先运行for的内容,运行速度非常快取决于内存的性能,函数体等for运行完之后i的值已经变成3即:i = 3;for循环执行完之后才能发生点击事件,不执行完点不上去,点完之后函数内就会去找i,但函数内部没有i,所以会到父级去找i,此时父级的 i 的值已经是3,所以会弹出3。

转载请注明原文地址: https://www.6miu.com/read-66432.html

最新回复(0)