作用域的原理,对JS将如何解析标识符做出了解答。而作用域的形成与执行环境和活动对象紧密相关。

我们对于JS标识符解析的判断,存在一个常见误区

首先,看一个关于JS标识符解析的问题 ,源于风雪之隅提出的问题

var name = 'globalName';
function funcA() {
console.log(name);
var name = 'funAName';
console.log(name);
console.log(age);
} funcA();

这段代码的运行结果是怎样的?

相信会有人跟我最初遇到这个问题时一样,以为结果会是这样:

globalName
funAName
[脚本错误: ReferenceError]

​ 我们认为:在funA中, 第一次console.log的时候,会取到全局变量name的值'globalName', 而第二次值被局部变量name覆盖, 所以第二次console.log是'funAName'。 而age属性没有定义, 所以脚本会出错。

但是实际上,运行结果是这样的:

undefined
funAName
[脚本错误: ReferenceError]

​ 为什么会这样呢?在JS中,标识符解析是沿作用域链一级一级地搜索标识符的过程,搜索过程始终从作用域链的前端开始,然后逐级地向后回溯,直到找到标识符为止(如果找不到标识符,通常会导致错误发生)。所以为了正确地判断标识符的解析结果,我们必须把作用域链原理弄清楚。

深入理解作用域原理能够为我们解密这个误区

​ 作用域链(scope chain)的生成跟执行环境(execution context)、函数对象(function object)和活动对象(activation object)紧密相关。

执行环境

​ 执行环境是JavaScript中最为重要的一个概念。执行函数定义了变量或函数有权访问的其它数据,决定了它们各自的行为。每个执行环境都有一个与之关联的变量对象(variable object)和一个作用域链(scope chain),环境中定义的所以变量和函数都保存在其变量对象中。执行环境分为两种,一种是全局执行环境,一种是函数执行环境。

  1. 全局执行环境

    ​ 全局执行环境是最外围的一个执行环境,其变量对象就是全局活动对象(window activation object),全局执行环境直到应用程序退出——例如关闭网页或浏览器——时才会被销毁。

  2. 函数执行环境

    ​ 每个函数都有自己的执行环境。当执行流进入一个函数时,函数环境就会被推入一个环境栈中。当函数执行完之后,栈将其环境弹出,把控制权返回给之前的执行环境。函数执行环境的变量对象是该函数的活动对象(activation object)。

作用域链

​ 对于每一个执行环境,都会创建一个与之关联的作用域链。每个执行环境的作用域链的前端,始终都是该执行环境的变量对象,对于全局执行环境就相当于window对象,对于函数执行环境就相当于该函数的活动对象;对于全局执行环境,已经是根部,没有后续,对于函数执行环境,其作用域链的后续是该函数对象的[[scope]]属性里的作用域链。

函数对象

​ 在一个函数定义的时候, 会创建一个这个函数对象的[[scope]]属性(内部属性,只有JS引擎可以访问, 但FireFox的几个引擎(SpiderMonkey和Rhino)提供了私有属性__parent__来访问它),并将这个[[scope]]属性指向定义它的作用域链上。 在这里的问题中,因为funcA定义在全局环境, 所以此时的[[scope]]只是指向全局活动对象window active object。

活动对象

​ 在一个函数对象被调用的时候,会创建一个活动对象,首先将该函数的每个形参和实参,都添加为该活动对象的属性和值;将该函数体内显示声明的变量和函数,也添加为该活动的的属性(在刚进入该函数执行环境时,未赋值,所以值为undefined,这个是JS的提前声明机制)。

​ 然后将这个活动对象做为该函数执行环境的作用域链的最前端,并将这个函数对象的[[scope]]属性里作用域链接入到该函数执行环境作用域链的后端。

现在让我们回到最初的问题

var name = 'globalName';
function funcA() {
//当funcA()被调用时,刚进入funcA的执行环境,其作用域链最前端的funA activation object里有name属性,值为undefined。
console.log(name);
var name = 'funAName';
console.log(name);
console.log(age);
} funcA();

​ 虽然感觉这个例子的误区跟JS提前声明机制的关系也很大,但是理解funA.[[scope]]属性的作用域链是funA定义时的作用域链,而不是被调用时的作用域链,对于看懂多层函数嵌套的情况下作用域链的坑,也是非常关键的。

JavaScript:理解执行环境、作用域链和活动对象的更多相关文章

  1. 深入理解javascript中执行环境(作用域)与作用域链

    深入理解javascript中执行环境(作用域)与作用域链 相信很多初学者对与javascript中的执行环境与作用域链不能很好的理解,这里,我会按照自己的理解同大家一起分享. 一般情况下,我们把执行 ...

  2. javascript中函数的执行环境、作用域链、变量对象与活动对象

    javascript高级程序设计中:对执行环境.作用域链.变量对象.活动对象的解释: 1.执行环境: 执行环境:有时也叫环境:是JavaScript中最为重要的一个概念:执行环境定义了变量或函数有权访 ...

  3. JavaScript之执行环境及作用域

        执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为.每个执行环境都有一个与之关联的变量对象,环境中定义的所有变量和函数都保存在这个对象中.我们编写的代码是无法访问这个对象的,但解 ...

  4. Javascript 的执行环境(execution context)和作用域(scope)及垃圾回收

    执行环境有全局执行环境和函数执行环境之分,每次进入一个新执行环境,都会创建一个搜索变量和函数的作用域链.函数的局部环境不仅有权访问函数作用于中的变量,而且可以访问其外部环境,直到全局环境.全局执行环境 ...

  5. javascript中执行环境和作用域(js高程)

    执行环境(execution context,为简单起见,有时也成为“环境”)是javascript中最为重要的一个概念.执行环境定义了变量或函数有权访问的其他数据,决定了它们各自的行为.每个执行环境 ...

  6. Javascript手记-执行环境和作用域

    执行环境是javascript一个重要的概念,执行环境定义了变量有权访问其他数据决定了他们各自的行为,每个执行环境 都有一个与之关联的变量,环境中定义的所有变量和函数都保存在这个对象中,虽然我们编写的 ...

  7. 从头开始学JavaScript (九)——执行环境和作用域

    原文:从头开始学JavaScript (九)--执行环境和作用域 一.执行环境:定义了变量或者函数有权访问的其他数据,决定了它们各自的行为.每个执行环境都有与之关联的变量对象. 变量对象:保存着环境中 ...

  8. 【进阶2-2期】JavaScript深入之从作用域链理解闭包(转)

    这是我在公众号(高级前端进阶)看到的文章,现在做笔记   https://github.com/yygmind/blog/issues/18 红宝书(p178)上对于闭包的定义:闭包是指有权访问另外一 ...

  9. JavaScript中执行环境和栈

    在这篇文章中,我会深入理解JavaScript最根本的组成之一 : "执行环境(执行上下文)".文章结束后,你应该对解释器试图做什么,为什么一些函数/变量在未声明时就可以调用并且他 ...

随机推荐

  1. chckBox样式的修改

    在Android开发中,系统自带的默认CheckBox由于比较简陋,可能难以满足部分人的审美需求,不过,Android具有很强的扩展性,自定义CheckBox其实也很简单. 1. Layout中定义C ...

  2. OOP 面向对象 七大原则 (一)

    OOP 面向对象   七大原则 (一) 大家众所周知,面向对象有三大特征继承封装多态的同时,还具有这七大原则,三大特征上一篇已经详细说明,这一篇就为大家详解一下七大原则: 单一职责原则,开闭原则,里氏 ...

  3. 【codeforces 803E】Roma and Poker

    [题目链接]:http://codeforces.com/contest/803/problem/E [题意] 给你一个不完整的胜负平序列(不完整是指中间有些地方为问号,让你自己选择胜负平) 让你复原 ...

  4. TensorFlow CNN 测试CIFAR-10数据集

    本系列文章由 @yhl_leo 出品,转载请注明出处. 文章链接: http://blog.csdn.net/yhl_leo/article/details/50738311 1 CIFAR-10 数 ...

  5. COCOS2DX 3.0 优化提升渲染速度 Auto-batching

    COCOS2DX 3.0 优化提升渲染速度 Auto-batching 近期在看COCOS2DX 3.0的Auto-batching合批与Auto Culling动态缩减功能以下就来细致看看吧:整合好 ...

  6. ADT、C和Java

    <编程导论(Java)·5 链表.数组和栈> 数据抽象使得用户程序猿在编写客户程序时,摆脱该数据类型的实现细节而只关心该数据类型的接口.在计算机科学中.有一些重要的数据抽象--数据结构,应 ...

  7. Codeforces 425A Sereja and Swaps(暴力枚举)

    题目链接:A. Sereja and Swaps 题意:给定一个序列,能够交换k次,问交换完后的子序列最大值的最大值是多少 思路:暴力枚举每一个区间,然后每一个区间[l,r]之内的值先存在优先队列内, ...

  8. hdoj--1028--Ignatius and the Princess III(母函数)

    Ignatius and the Princess III Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K ...

  9. 杂项:CMM

    ylbtech-杂项:CMM CMM是指“能力成熟度模型”,其英文全称为Capability Maturity Model for Software,英文缩写为SW-CMM,简称CMM.它是对于软件组 ...

  10. linux执行shell脚本时提示bad interpreter:No such file or directory的解决办法

    故障现象:在终端直接cd /var正常,在shell脚本中执行则报错.原因是脚本是在windows平台下写的,换行符与Linux不同,造成脚本不能正确执行 出现bad interpreter:No s ...