浅谈JS作用域
一、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标签
当中含有全局变量、全局函数(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阅读更多
- js重点浅谈(跨域,作用域和作用域链,闭包,原型和原型链继承)
- [转] 浅谈JS中的变量及作用域
- 浅谈js作用域和闭包
- 深入学习js之浅谈作用域(RHS和LHS)
- 深入学习js之浅谈作用域(隐藏作用域和块作用域)
- 深入学习js之浅谈作用域(作用域闭包)
- 浅谈JS中的!=、== 、!==、===的用法和区别 JS中Null与Undefined的区别 读取XML文件 获取路径的方式 C#中Cookie,Session,Application的用法与区别? c#反射 抽象工厂
- 浅谈js中对象的使用
- 浅谈js对象及对象属性
- JS学习3(变量、作用域和内存)
- JS管理作用域
- JS的解析顺序和作用域(严格模式)
- 浅谈实践在计算机专业本科教学中的作用
- JS高级程序设计第三版——变量、作用域和内存问题
- 浅谈使用element ui + vuedraggable + sortablejs实现多种版式布局及托拽(2)
- 关于js作用域总结,对妙味视频学习的总结
- 浅谈CTO的作用----软件公司如何开源节流(一)
- 浅谈JS中逗号运算符的用法
- 浅谈js中字符和数组一些基本算法题
- 浅谈SQL Server中的事务日志(五)----日志在高可用和灾难恢复中的作用