理解Js作用域和作用域链
来源:互联网 发布:线切割手动圆形编程 编辑:程序博客网 时间:2024/05/23 00:55
一、JavaScript作用域
任何程序设计语言都有作用域的概念,简单地说,作用域就是变量与函数可访问的范围,即作用域控制着变量与函数的可见性和生命周期。在Js中,变量的作用域分为全局作用域和局部作用域,相应的,变量分为全局变量和局部变量。
1、全局作用域
在代码中任何地方都可以访问到的对象拥有全局作用域。一般来说有以下几种情况:
1)、所有window对象拥有全局作用域
一般情况下,window对象的内置属性都拥有全局作用域,例如:window.name,window.top等。
2)、最外层函数以及最外层函数外面定义的变量(全局变量)拥有全局作用域。例如:
var people="xiaoming";function action(){ var a="dance"; function inner(){ alert(a); } inner();}alert(name);//xiaoming,name为全局变量alert(a);//错误,a为局部变量action();//danceinner()//错误
3)、所有未定义直接赋值的变量都是全局变量
function action(){ var a="dance"; b="sing";}alert(a);//错误,a为局部变量alert(b);//sing,b为全局变量
2、局部作用域
与全局作用域相反,局部作用域一般只在固定代码片段可访问到。最常见的例如函数内部声明的变量。例如下列代码中的变量a和函数inner都只拥有局部作用域。
var people="xiaoming";function action(){ var a="dance"; function inner(){ alert(a); } inner();}alert(name);//xiaoming,name为全局变量alert(a);//错误,a为局部变量action();//danceinner()//错误
3、补充说明:在Js中,没有块级作用域的概念。
如上所述,在Js中,没有块级作用域的概念。这意味着在块语句中定义的变量,实际上是包含在函数中而非语句中创建的。来看下面的例子。
function out(){ for(i=0;i<3;i++){ alert(i);//0,1,2 } alert(i);//3}out();//0,1,2,3
函数定义了一个for循环,变量i的值被初始化为0。在C++等其他语言中,变量i只会在for循环中有定义,循环一旦结束,变量i就会被销毁。然而在JavaScript中,变量i是定义在函数out()的活动对象中,因而从它有定义开始,就可以在函数内部随处访问它。
那么如何解决这一问题呢?我们可以用匿名函数来模仿块级作用域以避免上述问题。如下:
(function(){ //这里是块级作用域})();
此时,上面的例子则会变为:
function out(){ (function(){ for(i=0;i<3;i++){ alert(i);//0,1,2 } })(); alert(i);//导致一个错误!}
二、作用域链
当代码在一个环境中执行时,会创建变量对象(保存了该环境中定义所有变量和函数)的一个作用域链。作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。
作用域链的前端,始终都是当前执行的代码所在环境的变量对象。如果这个环境是函数,则将其活动对象(活动对象最开始时只包含一个变量,即arguments对象(这个对象在全局环境中是不存在的))作为变量对象。作用域链中的下一个变量对象来自包含环境(当前环境的父辈环境),而再下一个变量对象则来自下一个包含环境。这样,一直延续到全局执行环境。全局执行环境的变量对象始终都是作用域链的最后一个对象。
光看文字也许你有点晕,让我们来看一个简单的例子。
var color="blue";function changeColor(){ var anotherColor="red"; function swapColor(){ var tempColor=anotherColor; anotherColor=color; color=tempColor; //在这里可以访问到color,anotherColor,tempColor } //在这里可以访问到color,anotherColor}//在这里只访问到colorchangeColor();
上面共涉及到三个执行环境:全局环境,changeColor()局部环境以及swapColor()局部环境。
全局变量环境中有一个变量color和一个函数changeColor()。changeColor()局部环境中有一个变量anotherColor和一个函数swapColor()。但它也可以访问到全局环境中的color变量。swapColor()局部环境中有一个变量tempColor,该变量只可以在这个环境中访问到。然而在swapColor()内部则可以访问其他两个环境中的所有变量,因为那两个环境是它的父执行环境。
总而言之,内部环境可以通过作用域链访问所有的外部环境,但外部环境不能访问内部环境中的任何变量和函数。
在函数执行过程中,每遇到一个变量,都会经历一次标识符解析过程以决定从哪里获取和存储数据。该过程从作用域链头部,也就是从活动对象开始搜索,查找同名的标识符,如果找到了就使用这个标识符对应的变量,如果没找到继续搜索作用域链中的下一个对象,如果搜索完所有对象都未找到,则认为该标识符未定义。函数执行过程中,每个标识符都要经历这样的搜索过程。
- 理解Js作用域和作用域链
- js作用域和作用域链
- js作用域和作用域链
- js作用域和作用于链
- 理解js作用域原型链和执行上下文
- js和php中的作用域链的理解
- js作用域链和闭包的理解
- js深入理解之作用域链
- js的作用域链理解
- 理解 js的作用域
- 深入理解JavaScript作用域和作用域链
- 理解 JavaScript 作用域和作用域链
- 深入理解JavaScript作用域和作用域链
- 深入理解JavaScript作用域和作用域链
- 理解JavaScript作用域和作用域链
- 深入理解JavaScript作用域和作用域链
- 深入理解JavaScript作用域和作用域链
- 深入理解javascript作用域和作用域链
- 数据库第一范式,第二范式,第三范式
- 日志管理-aop
- react系列框架
- 使用@Controller注解为什么要配置<mvc:annotation-driven />
- 一、Rxjava从头学:响应式编程
- 理解Js作用域和作用域链
- 2016最流行的Android组件、工具、框架大全
- 图片的二次采样
- GIS软件开发工具包TatukGIS Developer Kernel v11.8发布,改进DWG阅读器
- <Qt>实例:视频播放器
- 如何处理数据库中ID重复的问题
- 关于Properties类读取properties文件时乱码问题
- 赶上RocketMq4.2.0更新这一波~~
- Oracle数据库中的分页--rownum