JavaScript深入之作用域链
前言
在 《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();
执行过程如下:
- checkscope 函数被创建,保存作用域链到内部属性[[scope]]
checkscope.[[scope]] = [
globalContext.VO
];
- 执行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]]]
}
- 准备工作做完,开始执行函数,随着函数的执行,修改AO的属性值
checkscopeContext = {
AO: {
arguments: {
length: 0
},
scope2: 'local scope'
},
Scope: [AO, [[Scope]]]
}
7.查找到scope2的值,返回后函数执行完毕,函数上下文从执行上下文栈中弹出
ECStack = [
globalContext
]
参考文章:https://github.com/mqyqingfeng/Blog/issues/2
JavaScript深入之作用域链的更多相关文章
- javascript的关键所在---作用域链
javascript的关键所在---作用域链 javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript ...
- javascript闭包和作用域链
最近在学习前端知识,看到javascript闭包这里总是云里雾里.于是翻阅了好多资料记录下来本人对闭包的理解. 首先,什么是闭包?看了各位大牛的定义和描述各式各样,我个人认为最容易一种说法: 外部函数 ...
- javascript笔记:javascript的关键所在---作用域链
javascript里的作用域是理解javascript语言的关键所在,正确使用作用域原理才能写出高效的javascript代码,很多javascript技巧也是围绕作用域进行的,今天我要总结一下关于 ...
- Javascript——闭包、作用域链
1.闭包:是指有权访问另一个函数作用域中的变量的函数.创建闭包的常见方式:在一个函数内部创建另一个函数. function f(name){ return function(object){ var ...
- [译]JavaScript:函数的作用域链
原文:http://blogs.msdn.com/b/jscript/archive/2007/07/26/scope-chain-of-jscript-functions.aspx 在JavaScr ...
- JavaScript中的作用域链原理
执行环境 作用域链的形成与执行环境(Execution Environment)相关,在JavaScript当中,产生执行环境有如下3中情形: 1 进入全局环境 2 调用eval函数 3 调用func ...
- 认识javascript范围和作用域链
范围 作用域就是变量和函数的可訪问范围.控制着变量和函数的可见性与生命周期,在JavaScript中变量的作用域有全局作用域和局部作用域. 全局和局部作用域以下用一张图来解释: 单纯的JavaScri ...
- javascript 关于 this 作用域链
使用 function f() {} 或者 var f = function() {} 来定义的函数,this 是指向 全局对象 var a = { b: 1, c: funct ...
- javascript深入浅出图解作用域链和闭包
一.概要 对于闭包的定义(红宝书P178):闭包就是指有权访问另外一个函数的作用域中的变量的函数. 关键点: 1.闭包是一个函数 2.能够访问另外一个函数作用域中的变量 文章首发地址于sau交流学习社 ...
随机推荐
- java中的a++与++a的区别
++a:如果++在前就会先把a+1. a++:如果++在后就会先a然后在执行++的操作.代码: int a = 1; System.out.pritln(++a); //输出2 int s = 1; ...
- 5款Python程序员高频使用开发工具推荐
很多Python学习者想必都会有如下感悟:最开始学习Python的时候,因为没有去探索好用的工具,吃了很多苦头.后来工作中深刻体会到,合理使用开发的工具的便利和高效.今天,我就把Python程序员使用 ...
- SpringBoot之整合Mybatis范例
依赖包: <?xml version="1.0" encoding="UTF-8"?> <project xmlns="http:/ ...
- 三、checkedListBoxControl
一.checkedListBoxControl的使用全选 private void InitDate() { CheckedListBoxItem[] itemArr = { new CheckedL ...
- 洛谷 P1141 01迷宫
看似普通的 bfs 题(实际上也不怎么难 主要是我太菜了) 题目链接:https://www.luogu.org/problemnew/show/P1141 如果直接用简单的bfs一顿求的话,会超时( ...
- Java 获取客户端ip返回127.0.0.1问题
Java开发中使用 request.getRemoteAddr 获取客户端 ip ,返回结果始终为127.0.0.1.原因是服务器使用了nginx反向代理. 解决办法:在nginx配置文件nginx. ...
- 【README.md】Markdown语言常用语法
转自:http://blog.csdn.net/zhaokaiqiang1992 这里只介绍最常用和最常见的功能,若想查看全部的语法,请移步http://wowubuntu.com/markdown/ ...
- windows下ping端口
上图的操作完成以后 进入dos控制台 输入telnet ip地址 端口号 回车 标识已ping通 ping不通是这种提示
- linux拷贝多个目录下的文件到同一个目录
拷贝a目录下的a.txt和b目录下的b.txt到c目录 cp -a \ /root/a/a.txt \ /root/b/b.txt \ /root/c/
- JS操作Cookies
JS操作Cookies 获取Cookie function getCookie(c_name) { if (document.cookie.length > 0) { c_start = doc ...