通过函数作用域和块级作用域看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实现的页内搜索代码
May 23 Javascript
基于jquery的自定义鼠标提示效果 jquery.toolTip
Nov 14 Javascript
基于jquery的跨域调用文件
Nov 19 Javascript
jquery图片轮播特效代码分享
Apr 20 Javascript
javascript中数组和字符串的方法对比
Jul 20 Javascript
微信和qq时间格式模板实例详解
Oct 21 Javascript
jQuery插件HighCharts绘制的基本折线图效果示例【附demo源码下载】
Mar 07 Javascript
vue-swiper的使用教程
Aug 30 Javascript
jQuery实现的点击显示隐藏下拉菜单功能完整示例
May 17 jQuery
Vue.js项目实战之多语种网站的功能实现(租车)
Aug 07 Javascript
D3.js 实现带伸缩时间轴拓扑图的示例代码
Jan 20 Javascript
Node.js API详解之 dns模块用法实例分析
May 15 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二维数组合并及去重复的方法
2015/03/04 PHP
PHP访问Google Search API的方法
2015/03/05 PHP
PHP简单获取多个checkbox值的方法
2016/06/13 PHP
PHP框架Laravel中使用UUID实现数据分表操作示例
2018/05/30 PHP
laravel 解决ajax异步提交数据,并还回填充表格的问题
2019/10/15 PHP
js图片延迟技术一般的思路与示例
2014/03/20 Javascript
director.js实现前端路由使用实例
2015/02/03 Javascript
js实现交换运动效果的方法
2015/04/10 Javascript
js实现获取鼠标当前的位置
2016/12/14 Javascript
浅谈react受控组件与非受控组件(小结)
2018/02/09 Javascript
关于React动态加载路由处理的相关问题
2019/01/07 Javascript
一秒学会微信小程序制作table表格
2019/02/14 Javascript
JavaScript中0、空字符串、'0'是true还是false的知识点分享
2019/09/16 Javascript
js+css3实现简单时钟特效
2020/09/13 Javascript
Python中Collection的使用小技巧
2014/08/18 Python
Python实现提取谷歌音乐搜索结果的方法
2015/07/10 Python
利用python模拟sql语句对员工表格进行增删改查
2017/07/05 Python
浅谈python的dataframe与series的创建方法
2018/11/12 Python
python tools实现视频的每一帧提取并保存
2020/03/20 Python
Python pandas自定义函数的使用方法示例
2019/11/20 Python
使用TensorFlow对图像进行随机旋转的实现示例
2020/01/20 Python
Pytorch .pth权重文件的使用解析
2020/02/14 Python
python 实现人和电脑猜拳的示例代码
2020/03/02 Python
python PIL模块的基本使用
2020/09/29 Python
python爬取2021猫眼票房字体加密实例
2021/02/19 Python
小程序瀑布流解决左右两边高度差距过大的问题
2019/02/20 HTML / CSS
意大利和国际奢侈品牌购物网站:Suitnegozi.com
2021/01/15 全球购物
审核会计岗位职责
2013/11/08 职场文书
学生出入校管理制度
2014/01/16 职场文书
大型晚会策划方案
2014/02/06 职场文书
八项规定整改方案
2014/02/21 职场文书
电子商务专业应届毕业生求职信
2014/06/21 职场文书
应届生求职信范文
2014/06/30 职场文书
影视广告专业求职信
2014/09/02 职场文书
2019下半年英语教师的教学工作计划(3篇)
2019/09/25 职场文书
mysql timestamp比较查询遇到的坑及解决
2021/11/27 MySQL