通过函数作用域和块级作用域看javascript的作用域链


Posted in Javascript onAugust 05, 2018

在ES6之前,javascript只有全局作用域和函数作用域。所谓作用域就是一个变量定义并能够被访问到的范围。也就是说如果一个变量定义在全局(window)上,那么在任何地方都能访问到这个变量,如果这个变量定义在函数内部,那么就只能在函数内部访问到这个变量。

全局作用域只要页面没关闭就会一直存在,而函数作用域只有在函数执行的时候才存在,执行完就销毁。且每次执行函数都会创建一个新的作用域。

那么什么是作用域链呢?
在了解作用域链之前,我们先了解一个执行期上下文的概念。

执行期上下文:当函数执行时,会创建一个称为执行期上下文的内部对象(即AO或GO),一个执行期上下文定义了一个函数的执行环境,函数每次执行时对应的执行期上下文都是独一无二的,所以每次调用一个函数都会创建一个新的执行期上下文,当函数执行完毕,所产生的执行期上下文被销毁。

作用域链就是函数中[[scope]]属性所存储的执行期上下文对象的集合,这个集合呈链式链接,我们把这种链式链接叫做作用域链。

作用域链更像是一种包含的关系。比如说函数A内部定义了一个函数B,所以B的定义是依赖于A的,也就是说B在A的内部,那么B中就可以访问A的中的变量和方法。这种一层一层向上依赖的关系就构成了作用域链。

为了更好理解,我们直接看例子。

var name = 'xiaoyu';
function fn1() {};
function fn2() {
 var num = 10;
 function fn3() {
  var num1 = 10;
  console.log(num);
 };
 return fn3;
}
var fn4 = fn2();

通过函数作用域和块级作用域看javascript的作用域链

在上个例子我们知道,fn2执行的时候返回fn3,产生了闭包。但是一个函数执行然后返回另一个函数都会产生闭包嘛?我们来看一下。

var name = 'xiaoyu';
function fn1() {};
function fn2() {
 var num = 10;
 function fn3() {//fn3函数没有依赖fn2函数内的变量
  var num1 = 10;
  console.log(num1);
 };
 return fn3;
}
var fn4 = fn2();

通过函数作用域和块级作用域看javascript的作用域链

了解了作用域链之后,我们来看一个小例子,巩固一下。

var age = 10;
var obj = {
 age: 12,
 test: function() {
  console.log(age);
  console.log(obj.age);
  console.log(this.age);
 }
}
obj.test();

console.log(this.age)打印出12不难理解,但是为什么console.log(age)不也应该打印出12嘛。

我们说test执行时首先会在自己的作用域内查看有没有age变量,然后再沿着作用域链往上到全局作用域查找age变量,全局作用域下有age变量和data变量。所以console.log(age)打印出的10,如果要打印出12则需要访问obj.age。

ES6的块级作用域

在ES6之后,通过let和const引入了块级作用域。即通过let和const声明的变量只在声明所在的块级作用域内有效,并且let声明的变量虽然属于全局变量,但不再属于全局对象window。

我们通过一段代码来看一下引入块级作用域后,函数的作用域链的变化。

var age = 10;
let obj = {
 age: 12,
 test: function() {
   console.log(age);
   console.log(obj.age);
   console.log(this.age);
 }
}
obj.test();

通过函数作用域和块级作用域看javascript的作用域链

Javascript 相关文章推荐
JS Timing
Apr 21 Javascript
兼容ie和firefox js关闭代码
Dec 11 Javascript
用 Javascript 验证表单(form)中的单选(radio)值
Sep 08 Javascript
asp.net中System.Timers.Timer的使用方法
Mar 20 Javascript
JS 去除Array中的null值示例代码
Nov 20 Javascript
jQuery实现摸拟alert提示框
May 22 Javascript
js的各种排序算法实现(总结)
Jul 23 Javascript
js动态添加的DIV中的onclick事件简单实例
Jul 25 Javascript
纯js实现手风琴效果代码
Apr 17 Javascript
javascript中活灵活现的Array对象详解
Nov 30 Javascript
JS拉起或下载app的实现代码
Feb 22 Javascript
vue项目打包后打开页面空白解决办法
Jun 29 Javascript
vue实现简单的MVVM框架
Aug 05 #Javascript
使用D3.js+Vue实现一个简单的柱形图
Aug 05 #Javascript
详解Require.js与Sea.js的区别
Aug 05 #Javascript
vue中关闭eslint的方法分析
Aug 04 #Javascript
详解Vue取消eslint语法限制
Aug 04 #Javascript
JavaScript原型对象、构造函数和实例对象功能与用法详解
Aug 04 #Javascript
JavaScript中变量、指针和引用功能与操作示例
Aug 04 #Javascript
You might like
php中使用getimagesize获取图片、flash等文件的尺寸信息实例
2014/04/29 PHP
PHP处理JSON字符串key缺少双引号的解决方法
2014/09/16 PHP
php实现微信公众平台账号自定义菜单类
2014/12/02 PHP
phpmailer简单发送邮件的方法(附phpmailer源码下载)
2016/06/13 PHP
php curl操作API接口类完整示例
2019/05/21 PHP
JS 字符串连接[性能比较]
2009/05/10 Javascript
查看源码的工具 学习jQuery源码不错的工具
2011/12/26 Javascript
JS 精确统计网站访问量的实例代码
2013/07/05 Javascript
浅谈javascript的调试
2015/01/28 Javascript
使用AngularJS创建自定义的过滤器的方法
2015/06/18 Javascript
JS返回只包含数字类型的数组实例分析
2016/12/16 Javascript
JavaScript 实现 Tab 点击切换实例代码
2017/03/25 Javascript
Angularjs在360兼容模式下取数据缓存问题的解决办法
2017/06/22 Javascript
jQuery获取所有父级元素及同级元素及子元素的方法(推荐)
2018/01/21 jQuery
如何使用VuePress搭建一个类型element ui文档
2019/02/14 Javascript
nodejs 递归拷贝、读取目录下所有文件和目录
2019/07/18 NodeJs
js回溯法计算最佳旅行线路代码实例
2019/09/11 Javascript
mpvue 页面预加载新增preLoad生命周期的两种方式
2019/10/17 Javascript
浅谈vue获得后台数据无法显示到table上面的坑
2020/08/13 Javascript
详解Python的Django框架中manage命令的使用与扩展
2016/04/11 Python
python3批量删除豆瓣分组下的好友的实现代码
2016/06/07 Python
简单实现python数独游戏
2018/03/30 Python
详解Python 数据库的Connection、Cursor两大对象
2018/06/25 Python
django-初始配置(纯手写)详解
2019/07/30 Python
Django框架HttpResponse对象用法实例分析
2019/11/01 Python
Python如何实现在字符串里嵌入双引号或者单引号
2020/03/02 Python
python操作链表的示例代码
2020/09/27 Python
Cpython解释器中的GIL全局解释器锁
2020/11/09 Python
日本无添加化妆品:HABA
2016/08/18 全球购物
施华洛世奇匈牙利官网:SWAROVSKI匈牙利
2019/07/06 全球购物
庆元旦广播稿
2014/02/10 职场文书
警示教育活动总结
2014/05/05 职场文书
干部作风整顿个人剖析材料
2014/10/06 职场文书
理想国读书笔记
2015/06/25 职场文书
CSS使用伪类控制边框长度的方法
2022/01/18 HTML / CSS
Pillow图像处理库安装及使用
2022/04/12 Python