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 相关文章推荐
用JTrackBar实现的模拟苹果风格的滚动条
Aug 06 Javascript
33个优秀的 jQuery 图片展示插件分享
Mar 14 Javascript
CSS(js)限制页面显示的文本字符长度
Dec 27 Javascript
javascript判断非数字的简单例子
Jul 18 Javascript
用JavaScript计算在UTF-8下存储字符串占用字节数
Aug 08 Javascript
javascript中in运算符用法分析
Apr 28 Javascript
基于jQuery实现左右图片轮播(原理通用)
Dec 24 Javascript
JavaScript拖拽、碰撞、重力及弹性运动实例分析
Jan 08 Javascript
JS字符串去除连续或全部重复字符的实例
Mar 08 Javascript
Vue监听事件实现计数点击依次增加的方法
Sep 26 Javascript
layui 上传文件_批量导入数据UI的方法
Sep 23 Javascript
JavaScript实现简单计算器功能
Dec 19 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经典的给图片加水印程序
2006/12/06 PHP
php面向对象全攻略 (十四) php5接口技术
2009/09/30 PHP
提高PHP编程效率的方法
2013/11/07 PHP
smarty中英文多编码字符截取乱码问题解决方法
2014/10/28 PHP
php+mysqli实现将数据库中一张表信息打印到表格里的方法
2015/01/28 PHP
php发送html格式文本邮件的方法
2015/06/10 PHP
redis+php实现微博(三)微博列表功能详解
2019/09/23 PHP
优化innerHTML操作(提高代码执行效率)
2011/08/20 Javascript
JS 屏蔽按键效果与改变按键效果的示例代码
2013/12/24 Javascript
高性能JavaScript模板引擎实现原理详解
2015/02/05 Javascript
深入理解JavaScript系列(38):设计模式之职责链模式详解
2015/03/04 Javascript
JavaScript之AOP编程实例
2015/07/17 Javascript
javascript表单验证大全
2015/08/12 Javascript
laypage分页控件使用实例详解
2016/05/19 Javascript
数组Array的一些方法(总结)
2017/02/17 Javascript
vue.js中npm安装教程图解
2018/04/10 Javascript
详解微信小程序input标签正则初体验
2018/08/18 Javascript
JavaScript继承的特性与实践应用深入详解
2018/12/30 Javascript
详解微信小程序实现仿微信聊天界面(各种细节处理)
2019/02/17 Javascript
vue的路由映射问题及解决方案
2019/10/14 Javascript
[46:16]2018DOTA2亚洲邀请赛3月30日 小组赛B组 iG VS VP
2018/03/31 DOTA
python面向对象_详谈类的继承与方法的重载
2017/06/07 Python
分享Pycharm中一些不为人知的技巧
2018/04/03 Python
Python中使用Counter进行字典创建以及key数量统计的方法
2018/07/06 Python
pandas 把数据写入txt文件每行固定写入一定数量的值方法
2018/12/28 Python
python opencv实现证件照换底功能
2019/08/19 Python
Python关于反射的实例代码分享
2020/02/20 Python
Python用dilb提取照片上人脸的示例
2020/10/26 Python
HTML5 Canvas阴影使用方法实例演示
2013/08/02 HTML / CSS
澳大利亚实惠时尚女装商店:Katies
2019/06/16 全球购物
留学自荐信
2013/10/10 职场文书
写给保洁员表扬信
2014/01/08 职场文书
习近平在党的群众路线教育实践活动总结大会上的讲话
2014/10/21 职场文书
教师党员自我评价范文
2015/03/04 职场文书
Java异常体系非正常停止和分类
2022/06/14 Java/Android
nginx之内存池的实现
2022/06/28 Servers