在 JavaScript 作用域不完全指北 中,我们介绍了作用域的概念以及 JavaScript 引擎、编译器和作用域的关系。作用域有两种主要的工作模型:词法作用域和动态作用域。其中最为普遍的也是大多数编程语言所采用的是词法作用域,我们主要对其进行研究学习。
在传统编译语言的流程中, 程序中的一段源代码在执行之前会经历三个步骤, 统称为“编译”。

  • 分词/词法分析(Tokenizing/Lexing)

这个过程会将由字符组成的字符串分解成(对编程语言来说) 有意义的代码块, 这些代码块被称为词法单元。

  • 解析/语法分析(Parsing)

这个过程是将词法单元流(数组) 转换成一个由元素逐级嵌套所组成的代表了程序语法结构的树。 这个树被称        为“抽象语法树”(Abstract Syntax Tree, AST)。

  • 代码生成

将“抽象语法树” 转换为可执行代码的过程称被称为代码生成。 这个过程与语言、 目标平台等息息相关。
第一个步骤也叫作词法化,词法作用域就是定义在词法阶段的作用域。简单地说,词法作用域是由你写代码时将变量和块作用域写在哪里来决定的,词法分析器处理代码时会保持作用域不变。
我们通过以下代码来分析一下词法作用域:

function foo(a){
var b = a * 2;
function bar(c){
console.log(a,b,c);
}
bar(b * 3);
}
foo(2); //2 4 12

在实例代码中,会有三个逐级嵌套的作用域。

1.包含着全局作用域,其中有一个标识符 foo

2.包含着 foo 所创建的作用域,其中有三个标识符:a,bar,b

3.包含着 bar 所创建的作用域,其中有一个标识符:c

引擎使用作用域的结构和相互之间的位置关系来查找标识符。我们在上篇文章中讲过,引擎在作用域中进行变量查找的过程,是从当前作用域逐级向外,直到遇到第一个匹配的标识符结束。
在实例代码中,引擎执行 console.log(a,b,c); 声明,并查找变量 a , b , c 的引用。首先从最内部的作用域,也就是 bar 函数的作用域开始查找,引擎无法在这里查找到变量 a ,便会到上一级所嵌套的 foo 函数作用域中进行查找。引擎在这里找到了变量 a 的引用,便会停止对变量 a 引用的查询。对 b 来说也是一样的。对 c 来说,引擎在 bar 函数作用域中就会找到它。
引擎会在作用域中找到第一个匹配的标识符时停止查找。也就是说,在多层的嵌套作用域中可以定义同名的标识符,内部的标识符会遮蔽外部的标识符,这叫作“遮蔽效应”。
词法作用域意味着作用域是由书写代码时函数的位置来决定的。编译的词法分析阶段基本能够知道全部标识符在哪里以及是如何声明的,从而预测在引擎执行代码过程中如何对它们进行查找。

参考

  • 《你不知道的JavaScript》
  • 《深入理解JavaScript特性》

作者:CoderFocus

微信公众号:

声明:本文为博主学习感悟总结,水平有限,如果不当,欢迎指正。如果您认为还不错,不妨点击一下下方的【推荐】按钮,谢谢支持。转载与引用请注明作者及出处。

JavaScript 词法作用域不完全指北的更多相关文章

  1. 网易JS面试题与Javascript词法作用域说明

    调用对象位于作用域链的前端,局部变量(在函数内部用var声明的变量).函数参数及Arguments对象都在函数内的作用域中--这意味着它们隐藏了作用域链更上层的任何同名的属性. 2010年9月14日, ...

  2. JavaScript词法作用域与调用对象

    关于 Javascript 的函数作用域.调用对象和闭包之间的关系很微妙,关于它们的文章已经有很多,但不知道为什么很多新手都难以理解.我就尝试用比较通俗的语言来表达我自己的理解吧. 作用域 Scope ...

  3. JavaScript词法作用域—你不知道的JavaScript上卷读书笔记(一)

    前段时间在每天往返的地铁上抽空将 <你不知道的JavaScript(上卷)>读了一遍,这本书很多部分写的很是精妙,对于接触前端时间不太久的人来说,就好像是叩开了JavaScript的另一扇 ...

  4. JavaScript 作用域不完全指北

    什么是作用域 对于几乎所有编程语言,最基本的功能之一就是能够存储变量的值,并且能在之后对这个值进行访问和修改.这样就会带来几个问题,这些变量存储在哪里?程序在需要的时候又是如何找到它们的?要解决这些问 ...

  5. JavaScript词法作用域经典练习题

    <!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...

  6. JavaScript的作用域与作用域链

    作用域 作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.可以说,变量和函数在什么时候可以用,什么时候被摧毁,这都与作用域有关. JavaScript中,变量的作用域有全局 ...

  7. JavaScript的作用域

    JavaScript的作用域主要是指函数的作用域,在进行结果判断的时候十分重要,如果不清楚作用域,便很有可能导致拿不到预期的结果,也就无法顺利的进行程序的编写,在经历了一系列的学习和了解之后,对相关知 ...

  8. javascript一个作用域案例分析

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  9. JavaScript夯实基础系列(一):词法作用域

      作用域是一组规则,规定了引擎如何通过标识符名称来查询一个变量.作用域模型有两种:词法作用域和动态作用域.词法作用域是在编写时就已经确定的:通过阅读包含变量定义的数行源码就能知道变量的作用域.Jav ...

随机推荐

  1. github网页

    GitHub主页 创建仓库 想必大家都有自己的Github账号吧,没有的可以到GitHub官网注册账号,注册完后,我们来下一步,在我们的GitHub上面右上角的New repository来创建一个仓 ...

  2. php 获取今日、昨日、本周,上周、本月,上月,季度的起始时间戳和结束时间戳的方法

    php 获取今日.昨日.上周.本月的起始时间戳和结束时间戳的方法,主要使用到了 php 的时间函数 mktime.下面首先还是直奔主题以示例说明如何使用 mktime 获取今日.昨日.上周.本月的起始 ...

  3. SQL Server修改标识列方法(备忘)

    原文:SQL Server修改标识列方法(备忘) SQL Server修改标识列方法 ----允许对系统表进行更新 exec sp_configure 'allow updates',1 reconf ...

  4. sql语句查询重复值

    select * from user where name in (select name from user group by name having count(*)>1)

  5. DataTable,DataView 排序和使用

    我们都知道在Sql Server可以用order by来排序,所以很多朋友在DataTable中排序也想到了用order by关键字.但这样实现是比较困难的,下面,我们讲解一种比较简单的方法: 控制台 ...

  6. delphi资源文件制作及使用详解

    一.引子:现在的Windows应用程序几乎都使用图标.图片.光标.声音等,我们称它们为资源(Resource).最简单的使用资源的办法是把这些资源的源文件打入软件包,以方便程序需要的时候调用.资源是程 ...

  7. Redis系统管理

    EXISTS/DEL exists <key>判断某个key是否存在 del <key>删除某个key *** TYPE/KEYS type <key>获取key的 ...

  8. QObject提供了QMetaObject元类信息(相当于RTTI和反射),信号与连接,父子关系,调试信息,属性,事件,继承关系,窗口类型,线程属性,时间器,对象名称,国际化

    元类信息(相当于RTTI和反射),信号与连接,父子关系,调试信息,属性,事件,继承关系,窗口类型,线程属性,时间器,对象名称,国际化其中元类又提供了:classInfo,className,构造函数, ...

  9. D7下FastMM的使用

    原文出处:http://hi.baidu.com/showwindows/blog/item/5b7ac601c487c605728da573.html FastMM 快速MM:-),在D2006和2 ...

  10. Qt之Model-View架构(雨田哥的博客)

    Qt之Model-View架构 Qt之Model-View架构 简述 效果图 代码 结尾 简述 为什么会用这个模式,这里我就不解释了,可以看下 豆子哥的见解 .这里我只是如何去使用的.供大家共同探讨学 ...