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 相关文章推荐
Google Suggest ;-) 基于js的动态下拉菜单
Oct 11 Javascript
JavaScript中“+”的陷阱深刻理解
Dec 04 Javascript
扩展jQuery对象时如何扩展成员变量具体怎么实现
Apr 25 Javascript
JS中获取函数调用链所有参数的方法
May 07 Javascript
jQuery实现的图文高亮滚动切换特效实例
Aug 10 Javascript
简单实现限制uploadify上传个数
Nov 16 Javascript
jQuery中delegate()方法的用法详解
Oct 13 Javascript
vue+element-ui动态生成多级表头的方法
Aug 28 Javascript
vue防止花括号{{}}闪烁v-text和v-html、v-cloak用法示例
Mar 13 Javascript
Vue登录拦截 登录后继续跳转指定页面的操作
Aug 04 Javascript
解决vue-router路由拦截造成死循环问题
Aug 05 Javascript
利用React高阶组件实现一个面包屑导航的示例
Aug 23 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 一元分词算法
2009/11/30 PHP
CI框架中cookie的操作方法分析
2014/12/12 PHP
php绘制一条弧线的方法
2015/01/24 PHP
PHP实现远程下载文件到本地
2015/05/17 PHP
php进行ip地址掩码运算处理的方法
2016/07/11 PHP
PHP多个图片压缩成ZIP的方法
2020/08/18 PHP
PHP依赖注入原理与用法分析
2018/08/21 PHP
Thinkphp5框架ajax接口实现方法分析
2019/08/28 PHP
解决ExtJS在chrome或火狐中正常显示在ie中不显示的浏览器兼容问题
2013/01/11 Javascript
单击浏览器右上角的X关闭窗口弹出提示的小例子
2013/06/12 Javascript
js操纵dom生成下拉列表框的方法
2014/02/24 Javascript
jQuery+css实现的换页标签栏效果
2016/01/27 Javascript
详解XMLHttpRequest(一)同步请求和异步请求
2016/09/14 Javascript
Node.js中环境变量process.env的一些事详解
2017/10/26 Javascript
完美解决手机浏览器顶部下拉出现网页源或刷新的问题
2017/11/30 Javascript
vue-cli 如何打包上线的方法示例
2018/05/08 Javascript
vue权限路由实现的方法示例总结
2018/07/29 Javascript
Easyui 关闭jquery-easui tab标签页前触发事件的解决方法
2019/04/28 jQuery
浅谈webpack构建工具配置和常用插件总结
2020/05/11 Javascript
js 动态校验开始结束时间的实现代码
2020/05/25 Javascript
vue实现简易图片左右旋转,上一张,下一张组件案例
2020/07/31 Javascript
SpringBoot+Vue 前后端合并部署的配置方法
2020/12/30 Vue.js
python实现删除文件与目录的方法
2014/11/10 Python
Python实现自动上京东抢手机
2018/02/06 Python
使用 Python 玩转 GitHub 的贡献板(推荐)
2019/04/04 Python
django Model层常用验证器及自定义验证器详解
2020/07/15 Python
Html5无刷新修改browser Url的方法
2014/01/15 HTML / CSS
大学生入党自我鉴定
2013/10/31 职场文书
办公室文书岗位职责
2013/12/16 职场文书
《我的第一本书》教学反思
2014/02/15 职场文书
护士感人事迹
2014/05/01 职场文书
暑期社会实践先进个人主要事迹
2014/05/22 职场文书
会计工作总结范文2014
2014/12/23 职场文书
埃及王子观后感
2015/06/16 职场文书
学生会工作感言
2015/08/07 职场文书
2016大一新生军训感言
2015/12/08 职场文书