day07--作用域

作用域:在一定的范围内,对其进行读、写操作
“js解析器”执行的过程至少2步
1、"找一些东西":比如 var 、function、参数
2、逐行解读代码

例:
alert(a);
var a=1;
function fn1(){
  alert(2);
}

解析过程:
1、JS的预解析过程  原则:遇到重名的:只留一个(变量和函数重名了,就只留下函数。无论变量在上还是函数在上,与上下是没关系的,跟有值没值有关系。因为变量=undefined,函数=整个函数块,相比之下有具体值的级别更大)


找到var关键字,然后定义其变量名等于undefined,不会管后面的值(在"JS解析器"执行的过程中,所有的变量都等于未定义)  如:a=undefined

找到function关键字,然后用其函数名等于其整个函数块。(所有的函数,在正式运行代码之前,都提前赋了一个值,这个值为整个函数块)  如:fn1=function fn1(){alert(2);}


2、逐行解读代码过程: 表达式可以修改"预解析"的值。函数的声明不属于表达式,改变不了什么东西
这个过程遵循"从上往下,从左往右"的顺序执行。
当执行一句完毕后,到仓库中查找是否有这个"东西"(变量、函数等)。如果有则弹出其一开始在仓库的值(使用alert方法)
遇到表达式(=+ - * / % ++ -- ! 参数……等即能改变值的东西)

简单来说,找var 、function、参数,并将变量赋值为undefined、函数名=整个函数,然后将他们存储在仓库中,在进行逐行解读代码的时候,在仓库中提取或修改


练习:


解析过程
1、找关键字(var、function、参数)
找到37行的"var a",执行过程:a=undefined
找到39行的"function a(){alert(2);}",执行过程:a=function a(){alert(2);}
因为仓库里有重名的a,所以要比较优先级,值为函数的大于值为未定义,所以执行过程为a=function a(){alert(2);}
找到41行的"var a ",执行过程:a=undefined
因为仓库里有重名的a,所以要比较优先级,值为函数的大于值为未定义,所以执行过程为a=function a(){alert(2);}
找到43行的"function (){alert(4);}",执行过程:a=function (){alert(4);}
因为仓库里有重名的a,所以要比较优先级,值同为函数则比较先后,后面的覆盖前面的,所以执行过程为a=function a(){alert(4);}
2、逐行解析:
从上往下,从左到右依次执行代码。从36行开始,a的一开始值为function a(){alert(4);}
执行37行时,修改仓库中a的值,则变为1
执行39行时,并不影响a的值,所以a的值还是1
后面亦是如此


一个页面两个script标签,浏览器遇到script标签会用"js解析器"来解析,只有解析完第一个script标签的内容后在执行下一个script标签内的内容,所以下面alert(a); 会报错  a is no defined。



这就是当引用别人写的jQuery库时,在对其修改


var a = 1;
function fn1(){
alert(a); //undefined
var a = 2;
}
fn1();
alert(a);                //1
解析过程:
1、预解析:
a=undefined;
fn1=function fn1(){   alert(a); var a = 2;}
2、逐行解析;
a=1
遇到函数调用fn1()    --函数也是一个局部的域,只要是一个域就会发生预解析和逐行解读代码。相当于其有一个小的仓库。可以理解为1个大仓库包含着1个小仓库,大仓库里的a和小仓库里的a是不同的世界,互不影响。函数调用属于表达式
  函数里的预解析:
     a=undefined;  //这里的a是局部的,外面的是全局的,两者没关系
  函数里的逐行解析:
     执行函数里的alert(a); 先找局部仓库里的a,所以弹出undefined
     在执行函数里的var a=2;  所以局部里的a=2,并没有影响全局中的a=1
  函数执行完毕后会有垃圾回收机制等

函数调用完毕后,继续全局的逐行解析



var a = 1;
function fn1(){
alert(a); // 1
a = 2;                      //注意这里没用var声明
}
fn1();
alert(a); // 2
函数里的预解析过程为空,执行函数里的逐行解析代码:当执行到alert(a);没找到a,会顺着函数的作用域跳到上一级(从子级作用域返回到父级作用域的过程叫作用域链,由里到外找)。执行到"a=2"时,发现小仓库里没有a,则由里到外找,找到其父级有a,则修改a的值为2

所以,加var与不加var的区别体现出来了。不加var,会修改全局变量的值



var a = 1;
function fn1(a){
alert(a); // undefined
a = 2;
}
fn1();
alert(a); // 1

参数本质就是一个局部变量。跟上面的其中一种情况(如下)很类似
函数预解析时没有发现var、function  ,却发现了参数,所以a=undefined。
然后逐行解读代码,当读到"alert(a);",执行结果为undefined
当读到"a=2;",它会就近找小仓库里有没有a,执行结果为a=2,全局的a还是1不影响


var a = 1;
function fn1(){
alert(a); // undefined
var a = 2;
}
fn1();
alert(a); // 1

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值