JavaScript 作用域链其实很简单
概念
作用域链的用途,是保证对执行环境有权访问的所有变量和函数的有序访问。其本质就是一个指向变量对象的指针列表。在js中,当某个函数被调用时,会创建一个执行环境(execution context)及相应的作用域链。然后使用arguments和其他命名参数的值来初始化函数的活动对象(activation object)。在作用域链中,外部函数的活动对象始终位于第二位,外部函数的外部函数的活动对象位于第三位,......直至作为作用域终点的全局执行环境。
(1) arguments和命名参数可以去看另一篇博客 JavaScript 神奇的参数。
(2) 活动对象: 在一个函数对象被调用的时候,会创建一个活动对象。该函数的命名参数和arguments参数数组会被添加为该活动对象的属性,同时该函数体内显示声明的变量和函数,也会添加为该活动对象的属性(因为JS的提前声明机制,所以并没有立即赋值,值为undefined)。
在函数执行过程中,为了读取和写入变量的值,就需要在作用域中查找变量。看下面的例子:
function compare(value1,value2) {
if (value1 < value2){
return -1;
}else if(value1 > value2){
return 1;
}else{
return 0;
}
} var result = compare(5,10);
以上代码先定义了compare()函数,然后在全局作用域中调用了它。当调用compare()时,会创建一个包含arguments、value1、value2的活动对象。全局执行环境的变量对象(包括result和compare)在compare() 执行环境的作用域中处于第二位。下图展示了包括上述关系的compare()函数执行时的作用域链。
从上图中可以看出compare的执行环境内部有一个属性指向当前作用域链,而compare()的活动对象就保存在作用域链的最前面(第一位)也就是下标为0的位置。全局执行环境的变量对象则处于第二位,也就是下标为1的位置。
过程大致为:在创建compare()函数时,会创建一个预先包含全局变量对象的作用域链,这个作用域链被保存在内部的[[Scope]]属性中。当调用compare()函数时,会为函数创建一个执行环境,然后通过复制函数的[[Scope]]属性中的对象构建起执行环境的作用域链。此后,又有一个活动对象被创建并推入执行环境作用域链的前端。对于这个例子中compare()函数的执行环境而言,其作用域中包含两个变量对象:本地活动对象和全局变量对象。从这里就可以看出,作用域链的本质就是一个指向量的指针列表,它只引用但不实际包含变量对象。
JavaScript 作用域链其实很简单的更多相关文章
- JavaScript作用域链
之前写过一篇JavaScript 闭包究竟是什么的文章理解闭包,觉得写得很清晰,可以简单理解闭包产生原因,但看评论都在说了解了作用域链和活动对象才能真正理解闭包,起初不以为然,后来在跟公司同事交流的时 ...
- JavaScript作用域链详解
JavaScript的作用域链还是很有味道的,搞懂了这个知识点,闭包的问题也就迎刃而解咯 1.JavaScript的全局变量和局部变量 首先,先来看看js的全局变量和局部变量,js不是块级作用域,所以 ...
- JavaScript作用域链的理解
前言 作用域是JavaScript一个很重要的概念,想要学好JavaScript就需要理解javascript作用域和作用域链的工作原理.这篇文章对JavaScript作用域链和作用域链做一个简单的介 ...
- JavaScript 作用域链图具体解释
<script type="text/javascript"> /** * 作用域链: */ var a = "a"; function hao94 ...
- 深入javascript作用域链到闭包
我之前用过闭包,用过this,虽然很多时候知道是这么一回事,但是确实理解上还不够深入.再一次看javascript高级程序设计这本书时,发现一起很多疑难问题竟然都懂了,所以总结一下一些理解,难免有错, ...
- javascript 作用域链及性能优化
在JavaScript中,函数也是对象,实际上,JavaScript里一切都是对象.函数对象和其它对象一样,拥有可以通过代码访问的属性和一系列仅供JavaScript引擎访问的内部属性.其中一个内部属 ...
- 个人理解的javascript作用域链与闭包
闭包引入的前提个人理解是为从外部读取局部变量,正常情况下,这是办不到的.简单的闭包举例如下: function f1(){ n=100; function f2(){ alert(n); } retu ...
- javascript作用域链学习笔记
作用域链 "JavaScript中的函数运行在它们被定义的作用域里,而不是它们被执行的作用域里." --权威指南 在JavaScript中,一切皆对象,包括函数.函数对象和其它对象 ...
- (好文推荐)一篇文章看懂JavaScript作用域链
闭包和作用域链是JavaScript中比较重要的概念,首先,看看几段简单的代码. 代码1: var name = "stephenchan"; var age = 23; func ...
随机推荐
- Ubuntu下创建新用户后,不能使用管理员用户下安装的Anaconda
解决办法: 将管理员用户下Anaconda的安装环境添加到新用户下的环境变量里,具体操作: 系统切换到新用户下: vim .bashrc #添加Anaconda的环境变量 source .bashrc ...
- opencv3 图像处理(一)图像缩放( python与c++ 实现)
opencv3 图像处理 之 图像缩放( python与c++实现 ) 一. 主要函数介绍 1) 图像大小变换 Resize () 原型: void Resize(const CvArr* src,C ...
- react 中的绑定事件
handleOpen = (e)=> { this.setState({ open: true }) } <Button color='primary' onClick={this.han ...
- hibernate05--list和iterator
package cn.bdqn.test; import java.util.Iterator; import java.util.List; import org.hibernate.Query; ...
- Java高并发系列 — AQS
只懂volatile和CAS是不是可以无视concurrent包了呢,发现一个好链接,继续死磕,第一日: 首先,我承认很多时候要去看源码才能更好搞懂一些事,但如果站在巨人肩膀上呢?有了大概思想源码看还 ...
- Java开发岗位面试题归类
一.Java基础 1. String类为什么是final的. ( 1.由于String类不能被继承,所以就不会被修改,这就避免了因为继承引起的安全隐患: 2.String类在程序中出现的频率比较高,如 ...
- vue路由动态加载
注意:是动态加载不是动态路由 解决的问题: 动态配置菜单栏的路由参数--实现菜单级的权限控制 问题成因: 在vue实例化的时候vuex.vue-router 就需要加载完毕,无法使用异步的方式从服务器 ...
- 使用 jQuery 调用 ASP.NET AJAX Page Method
文章来源:http://chungle.iteye.com/blog/406054 说到轻量级的客户端通信,我注意到大多数人喜欢使用 ASP.NET AJAX Page Method 多于 ASMX ...
- Oracle工具——ADRCI
ADRCI工具是Oracle11g才推出的新工具,主要用来管理alert文件.trace文件.dump文件.健康监事报告等. 这一篇简单介绍ADRCI工具. 用过11g的人都会发现,11g中alert ...
- Consul的应用
Consul在集群上的每一个节点(包括Server和Client)都运行一个Agent,通过这个Agent可以进行对Consul所提供的功能的操作,通过调用一系列HTTP API与Agent的交互即可 ...