前言

《javascript深入之执行上下文栈》 中讲到,当javascript代码执行一段可执行代码(executable code)时,会创建对应的执行上下文(execution context)。

对于每个执行上下文,都有三个重要属性:

  • 变量对象(variable object, VO)
  • 作用域链(scope chain)
  • this

今天重点讲作用域链。

作用域链

《javascript深入之变量对象》中讲到,当查找变量时候,会先从当前上下文的变量对象中查找,如果没有找到,就会从父级(词法层面上的父级)执行上下文的变量对象中查到,一直找到全局上下文的变量对象,也就是全局对象。这样由多个执行上下文的变量对象构成的链表就叫做作用域链。

下面,让我们以一个函数的创建和激活两个时期来讲解作用域链是如何创建和变化的。

函数创建

在《javascript深入之词法作用域和动态作用域》中讲到,函数的作用域是在函数定义的时候就决定了。

这是因为函数有一个内部属性[[scope]],当函数创建的时候,就会保存所有父变量对象到其中,你可以理解[[scope]]就是所有父变量对象的层级链,但是注意:[[scope]]并不代表完整的作用域链!

举个例子:

function foo(){
function bar(){
...
}
}

函数创建时,各自的[[scope]]为:

foo.[[scope]] = [
globalContext.VO
]; bar.[[scope]] = [
fooContext.AO,
globalContext.VO
]

函数激活

当函数激活时,进入函数上下文,创建VO/AO后,就会将活动对象添加到作用域链的前端。

这时候执行上下文的作用域链,我们命名为 Scope:

Scope = [AO].concat([[Scope]])

至此,作用域链创建完毕。

捋一捋

以下面的例子为例:结合之前讲的变量对象和执行上下文栈,我们来总结一下函数执行上下文中作用域链和变量对象的创建过程:

var scope = 'global scope';
function checkscope(){
var scope2 = 'local scope';
return scope2;
}
checkscope();

执行过程如下:

  1. checkscope 函数被创建,保存作用域链到内部属性[[scope]]
checkscope.[[scope]] = [
globalContext.VO
];
  1. 执行checkscope函数,创建checkscope函数执行上下文,checkscope函数执行上下文被压入执行上下文栈
ECStack = [
checkscopeContext,
globalContext
];

3.checkscope 函数并不立刻执行,开始做准备工作,第一步:复制函数[[scope]]属性创建作用域链

checkscopeContext = {
Scope: checkscope.[[scope]]
}

4.第二步:用arguments创建活动对象,随后初始化活动对象,加入形参、函数声明、变量声明

checkscopeContext = {
AO: {
arguments: {
length: 0
},
scope2: undefined
},
Scope: checkscope.[[scope]]
}

第三步:讲活动对象压入 checkscope作用域链顶端

checkscopeContext = {
AO: {
arguments: {
length: 0
},
scope2: undefined
},
Scope: [AO, [[Scope]]]
}
  1. 准备工作做完,开始执行函数,随着函数的执行,修改AO的属性值
checkscopeContext = {
AO: {
arguments: {
length: 0
},
scope2: 'local scope'
},
Scope: [AO, [[Scope]]]
}

7.查找到scope2的值,返回后函数执行完毕,函数上下文从执行上下文栈中弹出

ECStack = [
globalContext
]

参考文章:https://github.com/mqyqingfeng/Blog/issues/2

JavaScript深入之作用域链的更多相关文章

  1. javascript的关键所在---作用域链

    javascript的关键所在---作用域链 javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript ...

  2. javascript闭包和作用域链

    最近在学习前端知识,看到javascript闭包这里总是云里雾里.于是翻阅了好多资料记录下来本人对闭包的理解. 首先,什么是闭包?看了各位大牛的定义和描述各式各样,我个人认为最容易一种说法: 外部函数 ...

  3. javascript笔记:javascript的关键所在---作用域链

    javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript技巧也是围绕作用域进行的,今天我要总结一下关于 ...

  4. Javascript——闭包、作用域链

    1.闭包:是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式:在一个函数内部创建另一个函数. function f(name){ return function(object){ var ...

  5. [译]JavaScript:函数的作用域链

    原文:http://blogs.msdn.com/b/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx 在JavaScr ...

  6. JavaScript中的作用域链原理

    执行环境 作用域链的形成与执行环境(Execution Environment)相关,在JavaScript当中,产生执行环境有如下3中情形: 1 进入全局环境 2 调用eval函数 3 调用func ...

  7. 认识javascript范围和作用域链

    范围 作用域就是变量和函数的可訪问范围.控制着变量和函数的可见性与生命周期,在JavaScript中变量的作用域有全局作用域和局部作用域. 全局和局部作用域以下用一张图来解释: 单纯的JavaScri ...

  8. javascript 关于 this 作用域链

    使用 function f() {}  或者 var f = function() {}  来定义的函数,this 是指向 全局对象   var  a = {    b: 1,    c: funct ...

  9. javascript深入浅出图解作用域链和闭包

    一.概要 对于闭包的定义(红宝书P178):闭包就是指有权访问另外一个函数的作用域中的变量的函数. 关键点: 1.闭包是一个函数 2.能够访问另外一个函数作用域中的变量 文章首发地址于sau交流学习社 ...

随机推荐

  1. Object.prototype.toString.call()

    源码中有这样一段: class2type = {}, toString = class2type.toString,   function type(obj) { //obj为null或者undefi ...

  2. 结巴(jieba)分词

    一.介绍: jieba: “结巴”中文分词:做最好的 Python 中文分词组件 “Jieba” (Chinese for “to stutter”) Chinese text segmentatio ...

  3. k8s使用glusterfs做存储

    一.安装glusterfs https://www.cnblogs.com/zhangb8042/p/7801181.html 环境介绍; centos 7 [root@k8s-m ~]# cat / ...

  4. Fabric运维从入门到精通

    1. fabric的安装 在windows下的python3中安装fabric: 在python安装根目录下使用pip install fabric 安装 如图: fabric只支持python2不支 ...

  5. vue ajax

    局部get: this.$http.get(url,{param:jsonData}).then(successCallback,failCallBack) 局部post: this.$http.po ...

  6. vue axios 封装(三)

    封装三: import axios from 'axios' import { Message, MessageBox } from 'element-ui' import store from '. ...

  7. Linux命令替换字符串

    :%s/str1/str2/ 用str2替换str1

  8. BZOJ2176Strange string——最小表示法

    题目描述 给定一个字符串S = {S1, S2, S3 … Sn}, 如果在串SS中, 子串T(|T| = n)为所有长度为n的SS的字串中最小的(字符串的比较), 则称T为”奇怪的字串”. 你的任务 ...

  9. BZOJ4317Atm的树&BZOJ2051A Problem For Fun&BZOJ2117[2010国家集训队]Crash的旅游计划——二分答案+动态点分治(点分树套线段树/点分树+vector)

    题目描述 Atm有一段时间在虐qtree的题目,于是,他满脑子都是tree,tree,tree…… 于是,一天晚上他梦到自己被关在了一个有根树中,每条路径都有边权,一个神秘的声音告诉他,每个点到其他的 ...

  10. Codeforces Global Round 2 D. Frets On Fire (动态开点线段树,沙雕写法)

    题目链接:D. Frets On Fire 思路:明明可以离散化+二分写,思路硬是歪到了线段树上,自闭了,真实弟弟,怪不得其他人过得那么快 只和查询的区间长度有关系,排完序如果相邻的两个点的差值小于等 ...