通过函数作用域和块级作用域看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 表单取值赋值的一些基本操作
Oct 11 Javascript
juqery 学习之四 筛选过滤
Nov 30 Javascript
jquery validation验证身份证号,护照,电话号码,email(实例代码)
Nov 06 Javascript
动态加载jquery库的方法
Feb 12 Javascript
javascript正则匹配汉字、数字、字母、下划线
Apr 10 Javascript
Juery解决tablesorter中文排序和字符范围的方法
May 06 Javascript
jQuery ajaxSubmit 实现ajax提交表单局部刷新
Jul 04 Javascript
使用JQuery实现图片轮播效果的实例(推荐)
Oct 24 jQuery
JavaScript设计模式之缓存代理模式原理与简单用法示例
Aug 07 Javascript
vuex直接赋值的三种方法总结
Sep 16 Javascript
jQuery实现的老虎机跑动效果示例
Dec 29 jQuery
关于JavaScript 数组你应该知道的事情(推荐)
Apr 10 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生成带有雪花背景的验证码
2006/10/09 PHP
如何使用FireFox插件FirePHP调试PHP
2013/07/23 PHP
PHP JS Ip地址及域名格式检测代码
2013/09/27 PHP
php约瑟夫问题解决关于处死犯人的算法
2015/03/23 PHP
smarty模板引擎之内建函数用法
2015/03/30 PHP
PHP单例模式是什么 php实现单例模式的方法
2016/05/14 PHP
php中二分法查找算法实例分析
2016/09/22 PHP
laravel自定义分页的实现案例offset()和limit()
2019/10/15 PHP
Javascript 类与静态类的实现
2010/04/01 Javascript
js+数组实现网页上显示时间/星期几的实用方法
2013/01/18 Javascript
javascript Slip.js实现整屏滑动的手机网页
2015/11/25 Javascript
JavaScript中关联原型链属性特性
2016/02/13 Javascript
JavaScript学习笔记整理_用于模式匹配的String方法
2016/09/19 Javascript
微信小程序实现换肤功能
2018/03/14 Javascript
vue2 mint-ui loadmore实现下拉刷新,上拉更多功能
2018/03/21 Javascript
JavaScript中的"=、==、==="区别讲解
2019/01/22 Javascript
vue中使用百度脑图kityminder-core二次开发的实现
2019/09/26 Javascript
Vue实现PC端靠边悬浮球的代码
2020/05/09 Javascript
Python中字符串对齐方法介绍
2015/05/21 Python
python 移除字符串尾部的数字方法
2018/07/17 Python
用Pycharm实现鼠标滚轮控制字体大小的方法
2019/01/15 Python
Python3之不使用第三方变量,实现交换两个变量的值
2019/06/26 Python
Tensorflow实现神经网络拟合线性回归
2019/07/19 Python
Python 实现平台类游戏添加跳跃功能
2020/03/27 Python
Python pandas 列转行操作详解(类似hive中explode方法)
2020/05/18 Python
keras 实现轻量级网络ShuffleNet教程
2020/06/19 Python
基于Html5 canvas实现裁剪图片和马赛克功能及又拍云上传图片 功能
2019/07/09 HTML / CSS
百思买美国官网:Best Buy
2016/07/28 全球购物
新西兰演唱会和体育门票网站:Ticketmaster新西兰
2017/10/07 全球购物
美国生鲜及杂货电商:FreshDirect
2018/01/29 全球购物
新加坡最早生产电动滑板车的制造商之一:FunsToTheFore
2020/09/08 全球购物
写好自荐信的技巧
2013/11/08 职场文书
民主生活会发言材料
2014/10/20 职场文书
2014年幼儿园班级工作总结
2014/12/17 职场文书
2014年小学教导处工作总结
2014/12/19 职场文书
有关浪费资源的建议书
2015/09/14 职场文书