JavaScript进阶(二)词法作用域与作用域链实例分析


Posted in Javascript onMay 09, 2020

本文实例讲述了JavaScript词法作用域与作用域链。分享给大家供大家参考,具体如下:

一、作用域

域表示的就是范围,即作用域,就是一个名字在什么地方可以使用,什么时候不能使用。想了解更多关于作用域的问题推荐阅读《你不知道的JavaScript上卷》第一章(或第一部分),从编译原理的角度说明什么是作用域。概括的说作用域就是一套设计良好的规则来存储变量,并且之后可以方便地找到这些变量。

1.1 块级作用域

在C、Java、C#等编程语言中,下面的语法报错(伪代码)

{
  var num = 123;
  {
    console.log( num );  // num => 123
   }
}
console.log( num );  //报错

1.2 JS的词法作用域

所谓的词法(代码)作用域,就是代码在编写过程中体现出来的作用范围,代码一旦写好,不用执行,作用范围就已经确定好了,这个就是所谓的词法作用域。

在JS中词法作用域的规则:

  1. 函数允许访问函数外部的数据
  2. 整个代码结构中只有函数可以限定作用域
  3. 作用规则首先使用提升规则分析
  4. 如果当前作用域中有了名字了,就不考虑外面的名字

例子1:

var num = 123;
function foo(){
  console.log( num );
}
foo();  //123

例子2:

if( false ){
  var num = 123;
}
console.log( num ); //undefined

例子3:

var num = 123;
function foo () {
  var num = 456;
  function func(){
    console.log( num );
   }
   func();
}
foo();  //456

二、作用域链

只有函数才能制造作用域结构,那么只要是代码,至少有一个作用域,即全局作用域。

凡是代码中有函数,那么这个函数就构成另一个作用域。如果函数中还有函数,那么在这个作用域中就又可以诞生一个作用域,那么将这样的所有作用域列出来,可以有一个结构:函数内指向函数外的链式结构

例如:

function f1() {
  function f2() {
  }
}
var num = 456;
function f3() {
  function f4() {
  }
}

作用域链结构与DOM树结构很相似.

2.1 绘制作用域链

步骤:

  1. 看整个全局是一条链,即顶级链,记为0级链
  2. 看全局作用域中有什么成员声明,就以方格的形式绘制到0级链上
  3. 再找函数,只有函数可以限制作用域,因此从函数中引出新链,标记为1级链
  4. 然后在每一个1级链中再次往复刚才的行为

JavaScript进阶(二)词法作用域与作用域链实例分析

2.2 变量的访问(搜索)规则

  1. 首先看变量在第几条链上,在该链上看是否有变量的定义与赋值,如果有直接使用
  2. 如果没有到上一级链上找( n - 1 级链),如果有直接使用,停止继续查找。
  3. 如果还没有在此往上找… 直到全局链(0级),还没有就是is not defined
  4. 注意,切记:同级的链不可混合查找

绘制如下程序的作用域链

function f1() {
  var num = 123;
  function f2() {
    console.log( num ); 
   }
  f2();
}
var num = 456;
f1();  //123

JavaScript进阶(二)词法作用域与作用域链实例分析

函数f1 和变量 num=456, 在0级链,而f1下又可以展开1级链,1级链上有num=123和函数f2。程序f1()调用进入左边1级链,而f1中又调用了f2函数,f2函数中console.log(num)可以看作在2级链,此时,程序会向这一条链向上查找,首先2级链没有num,向上到达1级链,刚好1级链上有num=123,所以就直接使用123,程序最后的结果就是打印123.

2.3 如何分析代码

  1. 在分析代码的时候切记从代码的运行角度上来分析,如果代码给变量赋值了,一定要标记到图中
  2. 如果代码比较复杂,可以在图中表示代码的内容,有时候还要将原型图与作用域图结合起来分析

分析如下代码:

var num = 123;
function f1() {
  console.log( num );
}
function f2(){
  var num = 456;
  f1();
}
f2();  //123

作用域链图:

JavaScript进阶(二)词法作用域与作用域链实例分析

首先把num=123,函数f1,函数f2画在0级链上。f1中只有一句console,画出一条1级链,f2也下画出1级链,链上有num=456和函数调用语句f1();

调用f2(),进入f2函数的作用域链,而在f2中又调用了f1函数,程序进入f1的作用域链,所以console.log(num)会在此链上查找是否存在num,没有,继续向上一级链查找,刚好在0级链上找到了num=123,所以f1函数中的console.log(num)就是123.

感兴趣的朋友可以使用在线HTML/CSS/JavaScript代码运行工具:http://tools.3water.com/code/HtmlJsRun测试上述代码运行效果。

更多关于JavaScript相关内容可查看本站专题:《JavaScript常用函数技巧汇总》、《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

Javascript 相关文章推荐
JavaScipt中的Math.ceil() 、Math.floor() 、Math.round() 三个函数的理解
Apr 29 Javascript
js中的布尔运算符使用介绍
Nov 20 Javascript
js实现温度计时间样式代码分享
Aug 21 Javascript
第二次聊一聊JS require.js模块化工具的基础知识
Apr 17 Javascript
JS文件上传神器bootstrap fileinput详解
Jan 28 Javascript
Bootstrap选项卡动态切换效果
Nov 28 Javascript
微信JSAPI Ticket接口签名详解
Jun 28 Javascript
纯js代码生成可搜索选择下拉列表的实例
Jan 11 Javascript
clipboard.js在移动端复制失败的解决方法
Jun 13 Javascript
react组件从搭建脚手架到在npm发布的步骤实现
Jan 09 Javascript
JavaScript偏函数与柯里化实例详解
Mar 27 Javascript
Vue响应式原理Observer、Dep、Watcher理解
Jun 06 Javascript
JavaScript进阶(一)变量声明提升实例分析
May 09 #Javascript
JavaScript面向对象核心知识与概念归纳整理
May 09 #Javascript
Vue列表如何实现滚动到指定位置样式改变效果
May 09 #Javascript
Node.js API详解之 util模块用法实例分析
May 09 #Javascript
Vue实现PC端靠边悬浮球的代码
May 09 #Javascript
Auto.JS实现抖音刷宝等刷视频app,自动点赞,自动滑屏,自动切换视频功能
May 08 #Javascript
基于JavaScript实现表格隔行换色
May 08 #Javascript
You might like
PHP与MySQL交互使用详解
2006/10/09 PHP
DW中链接mysql数据库时,建立字符集中文出现乱码的解决方法
2010/03/27 PHP
JavaScript 原型链学习总结
2010/10/29 Javascript
无阻塞加载脚本分析[全]
2011/01/20 Javascript
拖动table标题实现改变td的大小(css+js代码)
2013/04/16 Javascript
js/jquery去掉空格,回车,换行示例代码
2013/11/05 Javascript
在JS中如何调用JSP中的变量
2014/01/22 Javascript
jQuery过滤HTML标签并高亮显示关键字的方法
2015/08/07 Javascript
javascript实现别踩白块儿小游戏程序
2015/11/22 Javascript
asp.net+jquery.form实现图片异步上传的方法(附jquery.form.js下载)
2016/05/05 Javascript
需灵活掌握的Bootstrap预定义排版类 你精通吗?
2016/06/20 Javascript
JS实现关闭当前页而不弹出提示框的方法
2016/06/22 Javascript
基于Three.js插件制作360度全景图
2016/11/29 Javascript
简单实现JS倒计时效果
2016/12/23 Javascript
js基于myFocus实现轮播图效果
2017/02/14 Javascript
微信小程序实现默认第一个选中变色效果
2018/07/17 Javascript
浅析Proxy可以优化vue的数据监听机制问题及实现思路
2018/11/29 Javascript
微信小程序登录按钮遮罩浮层效果的实现方法
2018/12/16 Javascript
详解vuejs2.0 select 动态绑定下拉框支持多选
2019/04/25 Javascript
Vue之beforeEach非登录不能访问的实现(代码亲测)
2019/07/18 Javascript
微信小程序点击生成朋友圈分享图(遇到的坑)
2020/06/17 Javascript
[01:13:08]2018DOTA2亚洲邀请赛4.6 淘汰赛 mineski vs LGD 第二场
2018/04/10 DOTA
python递归函数绘制分形树的方法
2018/06/22 Python
python爬虫框架scrapy实现模拟登录操作示例
2018/08/02 Python
Python读取xlsx文件的实现方法
2019/07/04 Python
react+django清除浏览器缓存的几种方法小结
2019/07/17 Python
python操作excel让工作自动化
2019/08/09 Python
简单的Python调度器Schedule详解
2019/08/30 Python
python实现将视频按帧读取到自定义目录
2019/12/10 Python
python selenium实现发送带附件的邮件代码实例
2019/12/10 Python
关于Keras Dense层整理
2020/05/21 Python
Pycharm 2020.1 版配置优化的详细教程
2020/08/07 Python
庆元旦活动总结
2014/07/09 职场文书
大学生求职信怎么写
2015/03/19 职场文书
调解书格式范本
2015/05/20 职场文书
初中政治教学工作总结
2015/08/13 职场文书