只要在<script></script>
标签中就是域,有域就要进行域解析(如何进行域解析参考上篇文章作用域 - JS解析器如何解析js代码?)。
如果一个页面中有两块标签。第二个域可以读取上一个域中的仓库。
所以一般我们引用库的时候会先把库写在上面,然后下面再写我们自己的js代码。
script:全局变量、全局函数;
函数、json对象也是域,只要是域就要进行域解析;
例1、
函数体内有var.
var a = 1;
function fn1(){
alert(a);//undefined
var a =2;
}
fn1();
alert(a);//1
解析:
第一步、预解析
1、首先读到第一行发现‘var’,于是存储‘a =undefined’;
2、读到第二行发现‘function’,于是存储‘fn1 = function fn1(){alert(a);var a =2;}’整个函数块都存储下来;
预解析结束。
第二步、逐行解析代码
1、第一行看到a,于是到仓库去找a,然后看到等号,就是表达式,会到仓库去更改值,由‘a=未定义’更改成‘a=1’;
2、第二行看到function函数,就是声明,不能对值进行修改,仓库中a 的值还是1不变。
3、继续读代码看到fn1();
函数调用,就是让函数里面的代码开始执行。我们知道函数也是一个域,只要是域就会发生域解析,于是函数里面的代码要先进行预解析,再逐行解读代码。如下:①②
①预解析:第一行alert(a);
没有要找的关键字;第二行var a =2;
看到var关键字,于是把a=未定义存储在仓库中。
②逐行解读代码:第一行看到a,于是到局部仓库去找a,弹出a=undefined;
第二行看到a,继续到仓库去找a.然后又看到等号,就是表达式,于是更改仓库中a的值为a=2;
注意:在函数内进行的预解析,跟函数外面仓库中的值没有关系。
4、继续读代码alert(a);
,看到a,然后到仓库去找a的值,a=1,弹出1。
例2、
当函数体内没有var。
var a = 1;
function fn1(){
alert(a);//1
a =2;
}
fn1();
alert(a);//2
解析:
第一步、预解析
1、首先读到第一行发现‘var’,于是存储‘a =undefined’;
2、读到第二行发现‘function’,于是存储‘fn1 = function fn1(){alert(a); a =2;}’整个函数块都存储下来;
预解析结束。
第二步、逐行解析代码
1、第一行看到a,于是到仓库去找a,然后看到等号,就是表达式,会到仓库去更改值,由‘a=未定义’更改成‘a=1’;
2、第二行看到function函数,就是声明,不能对值进行修改,仓库中a 的值还是1不变。
3、继续读代码看到fn1();
函数调用,就是让函数里面的代码开始执行。我们知道函数也是一个域,只要是域就会发生域解析,于是函数里面的代码要先进行预解析,再逐行解读代码。如下:①②
①预解析:第一行alert(a);
没有要找的关键字;第二行a =2;
也没有要找的关键字。于是预解析结束。局部仓库没有存储任何东西。
②逐行解读代码:第一行看到a,于是到局部仓库去找a,局部仓库没有找到a,于是从这层的作用域跳到外层作用域去找a(子集作用域到父级作用域去找,我们叫做作用域链),弹出a=1;第二行看到a,于是在局部作用域仓库找a,没有找到,于是到函数外面作用域继续找,找到a,然后又看到等号,于是把函数外面a的值更改为2,即仓库中存储的a = 2;
函数调用结束;
4、继续读代码‘alert(a);’,看到a,于是在仓库中找a ,找到a = 2,于是弹出2;
注意:子集作用域到父级作用域去找,我们叫做作用域链
例3、
当函数中有参数时
var a = 1;
function fn1(a){//添加参数
alert(a);//undefined
a =2;
}
fn1();
alert(a);
解析:
第一步、预解析
1、首先读到第一行发现‘var’,于是存储‘a =undefined’;
2、读到第二行发现‘function’,于是存储‘fn1 = function fn1(a){alert(a); a =2;}’整个函数块都存储下来;
预解析结束。
第二步、逐行解析代码
1、第一行看到a,于是到仓库去找a,然后看到等号,就是表达式,会到仓库去更改值,由‘a=未定义’更改成‘a=1’;
2、第二行看到function函数,就是声明,不能对值进行修改,仓库中a 的值还是1不变。
3、继续读代码看到fn1();
函数调用,就是让函数里面的代码开始执行。我们知道函数也是一个域,只要是域就会发生域解析,于是函数里面的代码要先进行预解析,再逐行解读代码。如下:①②
①预解析:函数第一行function fn1(a){
看到参数a,是要找的关键字;参数本质上就是局部变量,function fn1(var a)
,但是在函数调用时并没有传参进来,就相当于放着一个空值在这,即函数体的仓库中存放着a = 未定义;
由此局部预解析结束;
②逐行解读代码:第一行看到alert(a);
,于是到局部仓库去找a,局部仓库中a的值是未定义,所以弹出来undefined;继续读代码a =2;
,看到a后到局部仓库中去寻找a,然后看到等号,于是把局部仓库中a的值更改为a = 2;
函数调用解析结束;
4、继续解读代码,看到alert(a);
,于是到仓库中寻找a,弹出1(因为是到外面的大仓库中寻找,不是局部仓库)。