今天刚刚开通博客,也是第一次写博文,略感紧张。作为一个表达能力弱弱的人来说,自己花三分钟理解一个知识点,当别人问起时,也许需要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. lucene学习笔记:三,Lucene的索引文件格式

    Lucene的索引里面存了些什么,如何存放的,也即Lucene的索引文件格式,是读懂Lucene源代码的一把钥匙. 当我们真正进入到Lucene源代码之中的时候,我们会发现: Lucene的索引过程, ...

  2. 【hadoop代码笔记】Mapreduce shuffle过程之Map输出过程

    一.概要描述 shuffle是MapReduce的一个核心过程,因此没有在前面的MapReduce作业提交的过程中描述,而是单独拿出来比较详细的描述. 根据官方的流程图示如下: 本篇文章中只是想尝试从 ...

  3. POJ动态规划题目列表

    列表一:经典题目题号:容易: 1018, 1050, 1083, 1088, 1125, 1143, 1157, 1163, 1178, 1179, 1189, 1191,1208, 1276, 13 ...

  4. 产品经理如何赢得开发人员的尊重和支持?-摘自infoq

    对于产品经理来说,赢得开发人员的尊重和支持,从某种意义上讲,是产品迈向成功的坚实一步.最近,知乎社区上的开发人员和管理者在前.后两个帖子中对此展开了激烈的讨论,其中不乏真知灼见. 林志霖Cray认为产 ...

  5. lamda表达式相关知识

    lamda表达式写法 dt = datado.SelectDalMeath(sqlStr.ToString()); var x = (from r in dt.AsEnumerable() selec ...

  6. cocos2d-x图片变灰或者变亮

    //根据现有CCSprite,变亮和变灰 CCSprite* FlyLeaf::graylightWithCCSprite(CCSprite* oldSprite,bool isLight) {    ...

  7. ColorNote.疑难解答

    首先感谢你对colornote的支持 在使用此应用的过程中,存在任何问题,请先在此页面查看是否有对应的解决方案[Ctrl + F 搜索] 如果问题无法解决,请在页面下方留言,或者邮件light.z@q ...

  8. [iOS 多线程 & 网络 - 2.9] - ASI框架

    A.ASI基本知识 1.ASI简单介绍 ASI:全称是ASIHTTPRequest,外号“HTTP终结者”,功能十分强大. ASI的实现基于底层的CFNetwork框架,因此运行效率很高. ASI的g ...

  9. word2003公式编辑器公式显示不完整问题

    在段落里设置行距为:单倍行距.

  10. 修改eclipse默认编码方式

     设置js文件的默认编码格式为UTF-8                在Windows->Preference页面中,选择General->Content Types           ...