Javascript scrope
作用域:
顾名思义,就是能发生读写等操作的环境;但是又没这么简单,下面就来仔细撸一撸JS中的作用域。
*浏览器内部有读取JS的某段程序,当一段JS代码在浏览器中读到的时候,简单的来说会发生以下几个步骤:
1)预解析:
在代码解读之前发生,相当于一个"仓库",放一些东西,var、function、参数等,预解析时变量都是未定义的,函数则是整个函数块。当代码在一个环境中执行时,会创建变量对象的一个作用域链。是域就要预解析。
2)解读代码:
代码自上而下,从左往右的执行,读到表达式时,预解析仓库中的东西发生改变。
实例:
1
1 alert(a);// 报错 2 a=1;
预解析时由于没有var、function等,所以仓库为空。代码自上而下执行时a未定义报错。
2
1 alert(a); // function a(){alert(4);} 2 var a=1; 3 alert(a); // 1 4 function a(){ 5 alert(2); 6 } 7 alert(a);// 1 8 var a=3; 9 alert(a);// 3 10 function a(){ 11 alert(4); 12 } 13 alert(a); //3 14 a();// 报错 a() <=> 3(),number is not a function;*/
预解析时遇到重名的,会覆盖。变量与函数,留函数;函数与函数,留后面解析的。最后仓库里面有:a=function a(){alert(4);}函数块。
代码执行读到表达式,仓库内容改变,a变为表达式所赋予的值。然后接着读代码。
*注意:function a(){}是函数声明,没有调用,所以不执行,不会进行赋值操作。
3
1 var a=1; 2 function fn1(){ 3 alert(a); // undefined 4 var a=2; 5 } 6 fn1(); 7 alert(a); // 1
预解析仓库有:a=undefined、fn1=function fn1(){alert(a);var a=2;}
代码读到fn1()时,调用函数,函数内部发生预解析:
---a=1, fn1=function fn1(){alert(a);var a=2;}
------------undefined
继续执行,弹出undefined。
*注意 :函数内部 var a=2 是局部变量,不影响全局变量。
全局执行环境是最外围的一个执行环境,根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不一样,在web浏览器中,全局执行 环境被认为是windows对象;每个函数都有自己的执行环境。进到一个新环境,就会进行一次预解析。
4
1 var a=1; 2 function fn1(){ 3 alert(a); // 1 子级找不到;向父级找;由里到外; 作用域链 4 a=2; // 全局变量,改变值 5 } 6 fn1(); 7 alert(a); // 2
在子级执行环境中找不到变量,会沿着作用域链一级一级向外搜索,找到为止,找不到报错。
*注意:不声明而直接初始化的变量是全局变量,完全不推荐。
5
1 var a=1; 2 function fn1(a){ 3 alert(a); // undefined 4 a=2;//改变局部变量 5 } 6 fn1(); 7 alert(a); // 1
预解析仓库:a=undefined, fn1=function fn1(a){alert(a);a=2;}
读到fn1()时,调用函数,函数预解析
---a=1, fn1=function fn1(a){alert(a);a=2;}
-----------参数a=undefined
继续执行,弹出undefined、弹出1。
*注意:函数参数是局部变量,fn1(a) <=> fn1(var a=undefined)
6
1 var a=1; 2 function fn1(a){ // 参数a <=> var a=1 3 alert(a); // 1 这个a不是外面的a;这个是局部的 4 a=2; // 就近原则,改变了局部的a 5 } 6 fn1(a); 7 alert(a); // 1
相当于
1 var a=1; 2 function fn1(b){ //参数b <=> var b=a=1 3 alert(b); //1 4 b=2; 5 } 6 fn1(a); 7 alert(a); // 1

浙公网安备 33010602011771号