通过函数作用域和块级作用域看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 相关文章推荐
不错的一个日期输入 动态
Nov 06 Javascript
javascript下判断一个元素是否存在的代码
Mar 05 Javascript
javascript教程之不完整的继承(js原型链)
Jan 13 Javascript
JS字符串的切分用法实例
Feb 22 Javascript
jQuery实现放大镜效果实例代码
Mar 17 Javascript
javascript实现平滑无缝滚动
Aug 09 Javascript
javascript监听页面刷新和页面关闭事件方法详解
Jan 09 Javascript
详解使用angularjs的ng-options时如何设置默认值(初始值)
Jul 18 Javascript
JS使用tofixed与round处理数据四舍五入的区别
Oct 25 Javascript
详解vue微信网页授权最终解决方案
Jun 16 Javascript
初学vue出现空格警告的原因及其解决方案
Oct 31 Javascript
详解Javascript实践中的命令模式
May 05 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 获取远程文件大小的3种解决方法
2013/07/11 PHP
使用phpstorm和xdebug实现远程调试的方法
2015/12/29 PHP
如何写php守护进程(Daemon)
2015/12/30 PHP
JavaScript 新手24条实用建议[TUTS+]
2009/06/21 Javascript
JQuery Ajax通过Handler访问外部XML数据的代码
2010/06/01 Javascript
jQuery 中使用JSON的实现代码
2011/12/01 Javascript
JavaScript获取和设置CheckBox状态的简单方法
2013/07/05 Javascript
js判断字符长度以及中英文数字等
2013/12/31 Javascript
jQuery中width()方法用法实例
2014/12/24 Javascript
解析javascript中鼠标滚轮事件
2015/05/26 Javascript
jquery预加载图片的方法
2015/05/27 Javascript
javascript匀速运动实现方法分析
2016/01/08 Javascript
javascript使用闭包模拟对象的私有属性和方法
2016/10/05 Javascript
js学习笔记之事件处理模型
2016/10/31 Javascript
Bootstrap组合上、下拉框简单实现代码
2017/03/06 Javascript
详谈jQuery中的一些正则匹配表达式
2017/03/08 Javascript
微信小程序之数据缓存的实例详解
2017/09/29 Javascript
基于VUE.JS的移动端框架Mint UI的使用
2017/10/11 Javascript
vue组件之Alert的实现代码
2017/10/17 Javascript
Vue SPA单页应用首屏优化实践
2018/06/28 Javascript
node.js学习笔记之koa框架和简单爬虫练习
2018/12/13 Javascript
微信小程序实现批量倒计时功能
2020/11/01 Javascript
小程序实现简单语音聊天的示例代码
2020/07/24 Javascript
Vue实现省市区三级联动
2020/12/27 Vue.js
[01:56]无止竞 再出发——中国军团出征2017年DOTA2国际邀请赛
2017/07/05 DOTA
python3+selenium实现126邮箱登陆并发送邮件功能
2019/01/23 Python
Python找出列表中出现次数最多的元素三种方式
2020/02/24 Python
荷兰电脑专场:Paradigit
2018/05/05 全球购物
Visual-Click葡萄牙:欧洲领先的在线眼镜商
2020/02/17 全球购物
餐饮业创业计划书范文
2014/01/06 职场文书
家长对孩子的感言
2014/03/10 职场文书
家长通知书家长评语
2014/04/17 职场文书
汉语专业毕业生自荐信
2014/07/06 职场文书
餐饮店长岗位职责
2015/04/14 职场文书
医院见习总结
2015/06/24 职场文书
网络营销实训总结
2015/08/03 职场文书