通过函数作用域和块级作用域看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 相关文章推荐
JQuery实现点击div以外的位置隐藏该div窗口
Sep 13 Javascript
Js获取数组最大和最小值示例代码
Oct 29 Javascript
js实现ArrayList功能附实例代码
Oct 29 Javascript
javascript实现显示和隐藏div方法汇总
Aug 14 Javascript
DOM 事件的深入浅出(一)
Dec 05 Javascript
Angular 4依赖注入学习教程之ValueProvider的使用(七)
Jun 04 Javascript
通过学习bootstrop导航条学会修改bootstrop颜色基调
Jun 11 Javascript
vue多种弹框的弹出形式的示例代码
Sep 18 Javascript
AngularJS实现的select二级联动下拉菜单功能示例
Oct 25 Javascript
React Native开发封装Toast与加载Loading组件示例
Sep 08 Javascript
vue-router二级导航切换路由及高亮显示的实现方法
Jul 10 Javascript
详解vue身份认证管理和租户管理
May 25 Vue.js
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编写的导航条程序
2006/10/09 PHP
在PHP中利用wsdl创建标准webservice的实现代码
2011/12/07 PHP
PHP中redis的用法深入解析
2014/02/20 PHP
php中有关合并某一字段键值相同的数组合并的改进
2015/03/10 PHP
从盛大通行证上摘下来的身份证验证js代码
2011/01/11 Javascript
js实现拖拽 闭包函数详细介绍
2012/11/25 Javascript
JS 实现获取打开一个界面中输入的值
2013/03/19 Javascript
浅析Javascript使用include/require
2013/11/13 Javascript
在页面上用action传递参数到后台出现乱码的解决方法
2013/12/31 Javascript
jQuery针对各类元素操作基础教程
2014/08/29 Javascript
js使用DOM操作实现简单留言板的方法
2015/04/10 Javascript
JavaScript事件处理的方式(三种)
2016/04/26 Javascript
localStorage实现便签小程序
2016/11/28 Javascript
JavaScript中三个等号和两个等号你了解多少
2017/07/04 Javascript
AngularJS实现的select二级联动下拉菜单功能示例
2017/10/25 Javascript
webpack 单独打包指定JS文件的方法
2018/02/22 Javascript
JS实现全屏预览F11功能的示例代码
2018/07/23 Javascript
vue后台管理之动态加载路由的方法
2018/08/13 Javascript
JavaScript简单实现动态改变HTML内容的方法示例
2018/12/25 Javascript
vue实现父子组件之间的通信以及兄弟组件的通信功能示例
2019/01/29 Javascript
JS回调函数原理与用法详解【附PHP回调函数】
2019/07/20 Javascript
原生js实现3D轮播图
2020/03/21 Javascript
JavaScript实现简单进度条效果
2020/03/25 Javascript
python调用windows api锁定计算机示例
2014/04/17 Python
以Python的Pyspider为例剖析搜索引擎的网络爬虫实现方法
2015/03/30 Python
python实现用户登陆邮件通知的方法
2015/07/09 Python
详解Python中的__getitem__方法与slice对象的切片操作
2016/06/27 Python
Python Paramiko模块的使用实际案例
2018/02/01 Python
猎人靴英国官网:Hunter Boots
2017/02/02 全球购物
英国最大的化装舞会服装网站:Fancydress.com
2017/08/15 全球购物
用Java语言将一个键盘输入的数字转化成中文输出
2013/01/25 面试题
中专毕业生自我鉴定
2014/02/02 职场文书
廉洁校园实施方案
2014/05/25 职场文书
药房管理制度范本
2015/08/06 职场文书
Python机器学习之决策树和随机森林
2021/07/15 Javascript
mapstruct的用法之qualifiedByName示例详解
2022/04/06 Java/Android