例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。