通过函数作用域和块级作用域看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 相关文章推荐
Javascript 页面模板化很多人没有使用过的方法
Jun 05 Javascript
js hover 定时器(实例代码)
Nov 12 Javascript
购物车选中得到价格实现示例
Jan 26 Javascript
Node.js 制作实时多人游戏框架
Jan 08 Javascript
Javascript中常用的检测方法小结
Oct 08 Javascript
JavaScript函数基础详解
Feb 03 Javascript
详解在Vue中通过自定义指令获取dom元素
Mar 04 Javascript
简单谈谈React中的路由系统
Jul 25 Javascript
javascript获取图片的top N主色值方法详解
Jan 26 Javascript
Vue自定义指令封装节流函数的方法示例
Jul 09 Javascript
jQuery实现弹幕特效
Nov 29 jQuery
Vue前端项目部署IIS的实现
Jan 06 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中常用编辑器推荐
2007/01/02 PHP
PHP Google的translate API代码
2008/12/10 PHP
如何用php获取程序执行的时间
2013/06/09 PHP
PHP中把错误日志保存在系统日志中(Windows系统)
2015/06/23 PHP
Firefox div高度自适应
2009/04/28 Javascript
JS 文字符串转换unicode编码函数
2009/05/30 Javascript
JavaScript 获取事件对象的注意点
2009/07/29 Javascript
javascript 面向对象编程基础:封装
2009/08/21 Javascript
js 巧妙去除数组中的重复项
2010/01/25 Javascript
Javascript无阻塞加载具体方式
2013/06/28 Javascript
js简单的表格添加行和删除行操作示例
2014/03/31 Javascript
Google Maps API地图应用示例分享
2014/10/23 Javascript
JS实现淘宝支付宝网站的控制台菜单效果
2015/09/28 Javascript
使用Require.js封装原生js轮播图的实现代码
2017/06/15 Javascript
在 Angular中 使用 Lodash 的方法
2018/02/11 Javascript
微信小程序文章详情功能完整实例
2020/06/03 Javascript
解决await在forEach中不起作用的问题
2021/02/25 Javascript
[31:00]2014 DOTA2华西杯精英邀请赛5 24 NewBee VS iG
2014/05/25 DOTA
Python中的MongoDB基本操作:连接、查询实例
2015/02/13 Python
使用Python设置tmpfs来加速项目的教程
2015/04/17 Python
python中sys.argv参数用法实例分析
2015/05/20 Python
python绘制立方体的方法
2018/07/02 Python
Python绘制并保存指定大小图像的方法
2019/01/10 Python
Pycharm 设置默认头的图文教程
2019/01/17 Python
Python学习笔记之Break和Continue用法分析
2019/08/14 Python
Python如何计算语句执行时间
2019/11/22 Python
Django 再谈一谈json序列化
2020/03/16 Python
HTML5 input placeholder 颜色修改示例
2014/05/30 HTML / CSS
罗德与泰勒百货官网:Lord & Taylor
2016/08/12 全球购物
营销与策划专业毕业生求职信
2013/11/01 职场文书
初中生期末考试的自我评价
2013/12/17 职场文书
《跨越百年的美丽》教学反思
2014/02/11 职场文书
法律进企业活动方案
2014/03/04 职场文书
地球物理学专业推荐信
2014/09/08 职场文书
会计专业自荐信范文
2015/03/05 职场文书
python四种出行路线规划的实现
2021/06/23 Python