今天刚刚开通博客,也是第一次写博文,略感紧张。作为一个表达能力弱弱的人来说,自己花三分钟理解一个知识点,当别人问起时,也许需要30分钟才只是让别人知道自己在说什么,一点也不夸张,希望在博客上可以练习对语言的组织能力并记录学习笔记与大家一起交流。

  进入正题>>

首先,相关的概念定义如下:

  1. 执行环境: 所有 JavaScript 代码都是在一个执行环境中被执行的。执行环境是一个概念,一种机制,用来完成JavaScript运行时在作用域、生存期等方面的处理,它定义了变量或函数有权访问的其他数据(包含了外部数据),决定他们各自的行为。包括以下分类:

    全局执行环境: 全局环境是最外围的一个执行环境,根据ECMAScript实现所在的宿主环境不同,表示执行环境的对象也不一样,在web中,全局执行环境被认为是window对象。

   函数执行环境: 每个函数都有自己的执行环境。

  2. 变量对象: 每个执行环境都有一个变量对象与之关联,执行环境中定义的所有变量及函数(只包含在当前函数内定义的函数,局部变量)都保存在这个对象中,我们编写的代码无法直接访问这个对象,但解析器在处理数据时会在后台使用它。(参考下面的作用域,变量对象就是作用域为该执行环境的函数,变量的集合对象)

  3. 作用域: 变量或方法有访问权限的代码空间,即变量或函数起作用的区域。(作用域包括全局作用域与函数作用域,没有块级块作用域,即一个变量的作用域不可能是一个块级域,至少包括最临近的整个函数空间。)

  4. 作用域链: 由当前环境栈中对应的变量对象组成。作用域的用途,是保证对执行环境有权访问的所有变量和函数的有序访问,作用域前端,始终是当前执行的代码所在的环境对应的变量对象,下一变量对象来自包含(外部)环境,而再下一变量对象则来自下一包含环境,一直延续到全局执行环境。

以下分析将帮助大家理解上面的概念:

1. 执行环境与变量对象之间的对应关系

  每个执行环境会有一个变量对象与之关联,该变量对象保存了执行环境中定义的所有局部变量及函数,变量对象具有动态性,只有在定义变量的语句得到执行才会将该变量添加到变量对象中,如下例中

function showA () {
consoloe.log(a); // 变量对象中没有保存a
alert(a);
}

2. 程序执行时,环境栈与执行环境的关系

   当执行流进入一个函数时,即该函数正在执行,函数的执行环境就会被推入一个环境栈中,所有处在执行流的执行环境将有次序地保存在环境栈中,在函数执行之后,栈将其执行环境弹出,把控制权交给原来的执行环境。所以在程序执行中,环境栈是不断变化的,伴随着执行环境的出入,如下所示:

(摘自:笨蛋的座右铭的博文)

3. 理解环境栈,执行环境与作用域链之间的关系

  在某一时刻,环境栈中保存的执行环境是一定的,以下面的程序为例,当fn2正在执行时

function Fn1() {
var a = 1;
function Fn2() {
var b = 2;
}
Fn2(); // 当程序执行到此时
}
Fn1();

  此时环境栈状态如下:

此时环境栈包括:全局执行环境,fn1执行环境,fn2执行环境, 根据执行环境和变量对象具有的一一对应的关系,所以当前环境栈中执行环境和变量对象有以下对应关系

                              (摘自:笨蛋的座右铭的博文)

  根据作用域链的定义,由右边的变量对象所组成的就是当前作用域链,链的前端为Fn2执行环境对应的变量对象

4. 作用域链的作用(标识符解析机制)

  作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问(包括外部数据)

  标识符解析是沿着作用域链一级一级地搜索标识符的过程,搜索始终从作用域链的前端开始,然后逐级地向后回溯,直到找到标识符为止。

示例1:

var color = 'blue';
functionshowColor () {
 alert(color);
}
showColor(); // blue

  在例1中,标识符解析从作用域链前端开始,顺着作用域链往后找,开始在showColor()的执行环境对应的变量对象中未能找到,之外在包含环境(全局执行环境)的变量对象中找到color变量,停止搜索,所以此时的color变量引用了全局中定义的color变量,于是输出为blue;

例2:

var color = 'blue';
function showColor () {
var color = 'red';
 alert(color);
}
showColor(); // red

  在例2中,标识符解析从作用域链前端开始,顺着作用域链往后找,在showColor()函数对应的执行环境对应的变量对象找到变量color,标识符解析程序立即停止搜索,此时color变量为函数中定义的color,于是输出为red

  由以上两个例子中可以看出作用域链保证对执行环境有权访问的所有变量和函数的有序访问的原理:作用域链有序地保存了变量对象,由前向后,局部变量和函数往往保存在较前的变量对象中,因此被标识符解析的机会大于全局变量,也就有了局部变量会覆盖全局变量的现象,这样就保证了变量的有序访问。  

5. 作用域与变量对象,执行环境的关系

  由定义可知,作用域即函数或变量的作用区域。

  变量或函数具有作用域的原因,就是在环境中定义的变量仅保存在了该执行环境对应的对象变量中,执行环境在环境栈中弹出之后,作用域链中找不到该对变量对象,以下面为例

function showColor () {
var color = 'red';
}
showColor(); // red
alert(color); // color is undefined

  为什么在全局环境下showColor()内定义的变量不可访问呢,这是因为当函数执行到该语句时,color变量保存在了showColor()环境对应的变量对象中,现在showColor()已经执行完毕,该执行环境也从环境栈中弹出并销毁,所以此时的作用域链也不包括showColor()的执行环境对应的变量对象了,因为标识符解析是顺着作用域链查找变量的,所以这个过程不再能搜索到color变量,所以color变得只有定义该变量的函数中才能访问,具有一定范围的作用域。

以上内容为本人的理解,错误之处欢迎大家积极打脸~~

  

浅谈JS执行环境及作用域的更多相关文章

  1. js执行环境、作用域

    js执行环境.作用域 执行环境:是javascript中的一个重要的概念,<javascript高级程序设计第三版>的定义是:执行环境定义了变量或函数有权访问的其他数据,决定了他们各自的行 ...

  2. JS执行环境,作用域链及非块状作用域

    JS中的执行环境,顾名思义就是变量或函数所执行时的环境.在我的理解中,执行环境和作用域相差不大. 每个函数都有自己的执行环境,当执行流进入一个函数时,函数的环境就会被推入一个环境栈中.而在函数执行之后 ...

  3. 【repost】 原生JS执行环境与作用域深入理解

    首先,我们要知道执行环境和作用域是两个完全不同的概念. 函数的每次调用都有与之紧密相关的作用域和执行环境.从根本上来说,作用域是基于函数的,而执行环境是基于对象的(例如:全局执行环境即window对象 ...

  4. JS 执行环境与作用域链

    1.执行环境 JavaScript 代码都是在执行环境中被执行的.执行环境是一个概念,一种机制,用来完成JavaScript运行时在作用域.生命周期等方面的处理,它定义了变量或函数是否有权访问其他数据 ...

  5. 浅谈js执行机制

    关于js执行机制,老早之前就一直想写篇文章做个总结,因为和js执行顺序的面试题碰到的特别多,每次碰到总是会去网上查,没有系统地总结,搞得每次碰到都是似懂非懂的感觉,这篇文章就系统的总结一下js执行机制 ...

  6. 【原】javascript执行环境及作用域

    最近在重读<javascript高级程序设计3>,觉得应该写一些博客记录一下学习的一些知识,不然都忘光啦.今天要总结的是js执行环境和作用域. 首先来说一下执行环境 一.执行环境 书上概念 ...

  7. 浅谈 js eval作用域

    原文:浅谈 js eval作用域 就简单聊下如何全局 eval 一个代码. var x = 1; (function () { eval('var x = 123;'); })(); console. ...

  8. 浅谈 js 正则字面量 与 new RegExp 执行效率

    原文:浅谈 js 正则字面量 与 new RegExp 执行效率 前几天谈了正则匹配 js 字符串的问题:<js 正则学习小记之匹配字符串> 和 <js 正则学习小记之匹配字符串优化 ...

  9. js中的执行环境及作用域

    最近在面试时被问到了对作用域链的理解,感觉当时回答的不是很好,今天就来说说js中的作用域链吧. 首先来说说js中的执行环境,所谓执行环境(有时也称环境)它是JavaScript中最为重要的一个概念.执 ...

随机推荐

  1. Install_pygments

    安装Pygments语法高亮 On OS X Leopard, Snow Leopard 1 $ sudo easy_install Pygments Alternatively on OS X wi ...

  2. 复习C语言

    今天突然有感觉复习下C语言了,发现已经好久没有用过C编程了,话说最近都没有编过程序了都,趁现在还有点时间,好好学习下C了.话不多说上题目 请定义一个宏,比较两个数a.b的大小,不能使用大于.小于.if ...

  3. python编码问题的理解与解决

    错误:'ascii' codec can't encode characters in position 0-1: ordinal not in range(128) 看到网上很多都不清楚,做了一天的 ...

  4. CoffeeScript学习(1)——Quick Start

    什么是CoffeeScript CoffeeScript 是一门编译到 JavaScript 的小巧语言. 在 Java 般笨拙的外表下, JavaScript 其实有着一颗华丽的心脏. Coffee ...

  5. Spring AOP Interceptor transaction is not working

    Problem The Spring AOP transaction is not working in following interceptors? <bean id="testA ...

  6. jQuery基础学习3——jQuery库冲突

    默认情况下,jQuery用$作为自身的快捷方式. jQuery库在其他库之后导入 在其他库和jQuery库都被加载完毕后,可以在任何时候调用jQuery.noConflict()函数来将变量$的控制权 ...

  7. 开发程序过程中遇到的调用Web Api小问题

    在用Umbraco Web Api开发程序时,前端使用React调用Web Api 当时是有一个页面Search.cshtml,把用React产生的脚本代码,在这个页面进行引用 写了一个Api, 调用 ...

  8. 乐观锁--CAS

    悲观锁与乐观锁的区别 悲观锁会把整个对象加锁占为已有后才去做操作,Java中的Synchronized属于悲观锁.悲观锁有一个明显的缺点就是:它不管数据存不存在竞争都加锁,随着并发量增加,且如果锁的时 ...

  9. 多浏览器兼容flv视频播放HTML

    HTML: <object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http: ...

  10. 解决安装SQL Server2008失败的问题

    安装SQL Server2008时遇到"2008安装错误  必须重新启动计算机才能安装 SQL Server". 解决办法:HKEY_LOCAL_MACHINE\SYSTEM\Cu ...