javascript作用域和作用域链
2016-07-12 16:53
417 查看
1、作用域
作用域,它是指对某一变量和方法具有访问权限的代码空间。当我们在定义变量的时候,会定义两种变量,一种是在全局环境下定义的变量,叫全局变量,一种是在函数中定义的变量叫局部变量。全局变量的作用域就是全局环境,局部变量的作用域就是函数。
2、作用域链
javascript高级程序设计书中写到,当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。 作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量则来自下一个包含环境,这样一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。
简单来说就是,当我查找一个变量时,我会先在自己所在的环境找,找不到延着作用域链继续向外一层的环境找,找不到再向外找,一直找到全局执行环境中。
看一小段代码:
在上述代码中,你可以发现,标记为1的,三个颜色A、B、C都能正确的被找到并打印出来。而标记为2的,只能找到A、B颜色。而标记为3的,只能够找到A颜色。
出现这种情况的原因就是去查找变量值的时候,是先从自身所在的环境中查找,没找到的时候,沿着作用域链向外层查找,所以在内层可以访问到外层定义的变量,在外层是访问不到内层所定义的变量的。
3、块级作用域和函数作用域
我们都听说过javscript是没有块级作用域的,javascript执行的是函数作用域,那么什么是块级作用域呢?
任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。
什么是函数作用域?
简单来说函数中的参数和变量在函数外部是不可见的,只在函数内部可以访问。
为什么说javascript没有块级作用域,看一段以下代码:
会发现两个输出的都是blue,如果有块级作用域的话,if里面的color会被当做局部变量创建,这样子的话输出的就是"blue","red"了;正是因为没有块级作用域,if里面对color的赋值被当做是全局变量把原来的值覆盖掉,所以输出才会是两个都是blue;
4、变量声明提升
先来看一小段代码,你认为的输出是什么:
我们先不管上面的输出是什么,先来看看这几行代码的输出是什么;
console.log(a);var a = 123; //undefined;
console.log(a);var a ; //undefined;
var a = 123;console.log(a); //123;
出现这种情况就是因为变量声明提升,我们去声明一个变量的时候javascript引擎会把变量"提前"声明,而把赋值放在原来的顺序。
所以console.log(a);var a = 123;的执行顺序其实是var a; console.log(a); a = 123;
故输出a的时候只是创建了变量还没有被赋值,所以输出为undefined;
现在再来看看刚那段代码的执行顺序其实是:
注:对undefined作加减乘除会把它转化为数字类型,undefined转化为数字类型就是NaN;
故输出为 NaN 和 100 ;
作用域,它是指对某一变量和方法具有访问权限的代码空间。当我们在定义变量的时候,会定义两种变量,一种是在全局环境下定义的变量,叫全局变量,一种是在函数中定义的变量叫局部变量。全局变量的作用域就是全局环境,局部变量的作用域就是函数。
2、作用域链
javascript高级程序设计书中写到,当代码在一个环境中执行时,会创建变量对象的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。作用域链的前端,始终都是当前执行的代码所在环境的变量对象。 作用域链中的下一个变量对象来自包含(外部)环境,而再下一个变量则来自下一个包含环境,这样一直延续到全局执行环境;全局执行环境的变量对象始终都是作用域链中的最后一个对象。
简单来说就是,当我查找一个变量时,我会先在自己所在的环境找,找不到延着作用域链继续向外一层的环境找,找不到再向外找,一直找到全局执行环境中。
看一小段代码:
var colorA = "red"; function abc(){ var colorB = "blue"; function info(){ var color ="yellow"; console.log(colorA);-------1 console.log(colorB);-------1 console.log(colorC);-------1 }; info(); console.log(colorA);-------2 console.log(colorB);-------2 console.log(colorC);-------2 }; abc(); console.log(colorA);-------3 console.log(colorB);-------3 console.log(colorC);-------3
在上述代码中,你可以发现,标记为1的,三个颜色A、B、C都能正确的被找到并打印出来。而标记为2的,只能找到A、B颜色。而标记为3的,只能够找到A颜色。
出现这种情况的原因就是去查找变量值的时候,是先从自身所在的环境中查找,没找到的时候,沿着作用域链向外层查找,所以在内层可以访问到外层定义的变量,在外层是访问不到内层所定义的变量的。
3、块级作用域和函数作用域
我们都听说过javscript是没有块级作用域的,javascript执行的是函数作用域,那么什么是块级作用域呢?
任何一对花括号({和})中的语句集都属于一个块,在这之中定义的所有变量在代码块外都是不可见的,我们称之为块级作用域。
什么是函数作用域?
简单来说函数中的参数和变量在函数外部是不可见的,只在函数内部可以访问。
为什么说javascript没有块级作用域,看一段以下代码:
var color="red"; if(true){ var color = "blue"; console.log(color); } console.log(color);
会发现两个输出的都是blue,如果有块级作用域的话,if里面的color会被当做局部变量创建,这样子的话输出的就是"blue","red"了;正是因为没有块级作用域,if里面对color的赋值被当做是全局变量把原来的值覆盖掉,所以输出才会是两个都是blue;
4、变量声明提升
先来看一小段代码,你认为的输出是什么:
var a = 100; function testResult(){ var b = 2 * a; var a = 200; var c = a / 2; console.log(b); console.log(c); } testResult();
我们先不管上面的输出是什么,先来看看这几行代码的输出是什么;
console.log(a);var a = 123; //undefined;
console.log(a);var a ; //undefined;
var a = 123;console.log(a); //123;
出现这种情况就是因为变量声明提升,我们去声明一个变量的时候javascript引擎会把变量"提前"声明,而把赋值放在原来的顺序。
所以console.log(a);var a = 123;的执行顺序其实是var a; console.log(a); a = 123;
故输出a的时候只是创建了变量还没有被赋值,所以输出为undefined;
现在再来看看刚那段代码的执行顺序其实是:
var a = 100; function testResult(){ var b; var a; var c; b = 2 * a; //此时在局部变量中找到了a,故不会再向上找全局变量a = 100; 但是a还没被赋值,a为undefined,故此时b为NaN; a = 200; c = a / 2; // 100; console.log(b); //NaN console.log(c); //100 } testResult();
注:对undefined作加减乘除会把它转化为数字类型,undefined转化为数字类型就是NaN;
故输出为 NaN 和 100 ;
相关文章推荐
- <a>标签跳转和执行js函数,href和onclick属性
- JS-正则表达式2
- javascript闭包实例
- 五句话搞定JavaScript作用域
- 个人qq、营销qq加入页面内
- JavaScript导航脚本判断当前导航
- js和zclip实现复制内容到剪贴板效果
- javascript基础:表单处理2
- 输入框内只能输入数字,输入其他内容不显示
- javascript深入理解js闭包
- 初步学习JS中的闭包
- html用js实现导航栏的二级菜单,自动伸缩。。。
- 多么痛领悟的教训,提交js表单,服务器端接收不了表单内的文本值
- c# 在.NET使用Newtonsoft.Json转换,读取,写入json
- Js 中的preventDefault 和 stopPropagation 方法
- 判断页面div是否在显示范围之内
- 学习Javascript闭包(Closure)
- 判断滚动条是上滑还是下滑
- js获取url参数值的两种方式
- EXT 3.x 使用详解之fileUpload处理返回值json问题 <pre></pre>