一、js作用域概念---预解析规则,表达式
域:指的是一个空间、范围、区域
作用:通常指读和写
所以
作用域:指的是在一个范围内进行读或写的操作
浏览器中对js代码进行操作的是js解析器
js解析器的作用是:
1.“找一些东西”(var关键字、函数、参数)
var a=1;
function fn1(){
alert(2);
}
在上面的代码中,
a=未定义;
即:所有变量在正式运行之前都被赋了一个值:未定义
fn1 = function fn1(){
alert(2);
}
即:所有的函数在正式运行代码之前都是整个函数块
注意:在js预解析中,遇到重名变量和函数时,只留函数。
2.逐行解读代码
通过表达式解读代码( = + * / % ++ -- ! Number() 参数)
解析代码的过程是从仓库里找东西
注意:表达式可以修改预解析内的值
二、全局与局部作用域解析以及作用域链
域的形成在js当中有两种
1.<script></script>
当中含有全局变量、全局函数(window)
读取的方式是自上而下
2.函数(作用域链)
读取的方式是由里到外
在js高程中有介绍道:作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问(其实和我总结的一样啦~~)
下面我们来看一个代码:
例1
alert(a); //function a(){alert(4);}
var a=1;
alert(a); //1
function a(){alert(2);}
alert(a); //1
var a=3;
alert(a); //3
function a(){alert(4)}
alert(a); //3 //typeof(a) 为number
a(); //报错
解析:
第一步“找” 首先解析器先找关键字找到var a=未定义,然后又找到函数a=function a(){alert(2);},则覆盖原来的a=未定义;然后又找到a =未定义;无法覆盖,继续往下,找到a=function a(){alert(4)};现在在仓库里存入a=function a(){alert(4)};
第二步“读”从上往下看,读到alert(a),从仓库里找到刚才存入的a=function a(){alert(4)},所以输出;然后再往下第二行看见’=‘,则覆盖原来的函数,修改了原来仓库里的值使a=1;所以下一步输出a=1;再往下,函数中没有关键字,不修改仓库里的值,继续往下输出a=1;同理看见=;修改为a=3,然后输出。一直到最后a的值也是3。
但是当调用a();这个函数时,会报错,因为在仓库里a是一个变量不是一个函数。
再举一个例子:
例2
var a=1;
function fn1(){
alert(a); //a=未定义
var a=2;
}
fn1();
alert(a); //a=1
解析:
1.存入仓库里的是
a=未定义
fn1()=function fn1(){
alert(a);
var a=2;
}
自上而下往下读时,第一行有=;所以a=1;第二行函数不管,一直到调用fn1时,进入函数内部;
注意1:函数内部也是类似于作用域,分为两步;找东西和逐行读代码
进入函数内部之后,找到var a=.. ,所以函数内部仓库a=未定义;现在开始读代码,alert输出a=未定义;再往下,遇到=,给a赋值a=2;跳出函数继续往下,alert(a);
注意2:函数内部的为局部变量,现在浏览器访问到全局的仓库里找到a=1,所以输出a=1;
*局部作用域可以访问全局
同理,我再将上边的代码修改一下(将函数内部的var删除):
例3
var a=1;
function fn1(){
alert(a); //a=1
a=2;
}
fn1();
alert(a); //a=2
解析:与原来不同的是,函数内部仓库里找不到a存的值,或者换句话说,没有存入a,则需要从外部调取,所以a=1;同时函数内部修改了a的值,改为a=2;值得一提的是,此时修改的是全部变量的值,所以当函数调用完之后输出的是a=2
例4
var a=1;
function fn1(a){
alert(a); //a=未定义
a=2;
}
fn1();
alert(a); //a=1
解析:第一步,a存入仓库:a=未定义,然后开始读代码,读取第一行使a=1;再读入函数调用,调用函数时发现函数调用使用了参数,参数a=var a...将其存入函数内部仓库,所以函数内部输出alert(a)时,a=未定义,下一步修改函数内部a=2,跳出函数;alerta(a)时,调用的是全局变量所以输出a=1;
三、调用函数局部是数据,全局声明以及for嵌套中i的取值
例5
var a=1;
function fn1(a){
alert(a);
a=2; //a=1
}
fn1(a);
alert(a); //a=1
解析:第一步,a存入仓库:a=未定义,然后开始读代码,读取第一行使a=1;再读入函数调用,调用函数时发现函数调用使用了参数,参数a = var a = 1;因为fn1(a)中的a来自全局,所以当读取函数内部的alert(a)时a=1;下一步修改函数内部a=2,跳出函数;alerta(a)时,调用的是全局变量所以输出a=1;
我们需要始终记住作用域的特点:先解析再执行
当然,如果我们想获取函数内部的值,就是获取局部变量的值
可以通过下面两个办法:
1.利用全局变量赋值获取
例6
var str ='';
function a(){
a='999';
str =a ;
}
alert(str);
2.通过函数调用
例7
function fn2(){
var a ='999';
fn3();
}
fn2();
function fn3(d){
alert(d);
}
例8
alert( fn1 );
var a = 1;
function fn1(){
alert(123);
}
if( true ){
}
firefox不能对下面的函数进行预解析
对于for或者if嵌套,在js高程里称作“没有块级的作用域”,上面解释道:以for语句为例,由for创建的变量i即使在for循环执行结束后,也会依旧存在于循环外部的执行环境中。
例8
for(var i=0;i<10;i++){
dosomething();
}
alert(i) //i=10
网友评论