JavaScript 词法作用域不完全指北
在 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特性》
JavaScript 词法作用域不完全指北的更多相关文章
- 网易JS面试题与Javascript词法作用域说明
调用对象位于作用域链的前端,局部变量(在函数内部用var声明的变量).函数参数及Arguments对象都在函数内的作用域中--这意味着它们隐藏了作用域链更上层的任何同名的属性. 2010年9月14日, ...
- JavaScript词法作用域与调用对象
关于 Javascript 的函数作用域.调用对象和闭包之间的关系很微妙,关于它们的文章已经有很多,但不知道为什么很多新手都难以理解.我就尝试用比较通俗的语言来表达我自己的理解吧. 作用域 Scope ...
- JavaScript词法作用域—你不知道的JavaScript上卷读书笔记(一)
前段时间在每天往返的地铁上抽空将 <你不知道的JavaScript(上卷)>读了一遍,这本书很多部分写的很是精妙,对于接触前端时间不太久的人来说,就好像是叩开了JavaScript的另一扇 ...
- JavaScript 作用域不完全指北
什么是作用域 对于几乎所有编程语言,最基本的功能之一就是能够存储变量的值,并且能在之后对这个值进行访问和修改.这样就会带来几个问题,这些变量存储在哪里?程序在需要的时候又是如何找到它们的?要解决这些问 ...
- JavaScript词法作用域经典练习题
<!DOCTYPE html> <html lang="zh-CN"> <head> <meta charset="UTF-8& ...
- JavaScript的作用域与作用域链
作用域 作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.可以说,变量和函数在什么时候可以用,什么时候被摧毁,这都与作用域有关. JavaScript中,变量的作用域有全局 ...
- JavaScript的作用域
JavaScript的作用域主要是指函数的作用域,在进行结果判断的时候十分重要,如果不清楚作用域,便很有可能导致拿不到预期的结果,也就无法顺利的进行程序的编写,在经历了一系列的学习和了解之后,对相关知 ...
- javascript一个作用域案例分析
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- JavaScript夯实基础系列(一):词法作用域
作用域是一组规则,规定了引擎如何通过标识符名称来查询一个变量.作用域模型有两种:词法作用域和动态作用域.词法作用域是在编写时就已经确定的:通过阅读包含变量定义的数行源码就能知道变量的作用域.Jav ...
随机推荐
- 王立平--RemoteView
RemoteView它将在两个地方被使用:一个是在AppWidget,另外一个是在Notification. RemoteView是用来描写叙述一个垮进程显示的view 1.AppWidget---R ...
- 在Linux下使用MinGW静态交叉编译带有zlib的libcurl(包括交叉编译openssl,即--cross-compile-prefix=i686-w64-mingw32- mingw)
在Linux下使用MinGW静态交叉编译带有zlib的libcurl libcurl是一个跨平台的.易用的.强大的网络库.在大部分Linux发行版中都有编译好的二进制包可供使用,Mac系统更是将其作为 ...
- Android开发四大件
四大组件 Activity Activity是Android应用程序的界面,比如查看联系人.打电话.玩游戏的界面等一个应用程序通常包含多个Activity,即多个界面Activity通过布局管理各种V ...
- JS的innerText和innerHTML
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- 前端开发常用PhotoShop快捷键整理(更新中)
图片来源 UI提供的psd图 印屏幕:PrScrn SysRq(键盘按键) 浏览器(插件)获取 常用的快捷键: 新建 Ctrl + N 取消选框 Ctrl + D 反选 Ctrl + shift + ...
- WPF中的多进程(Threading)处理实例(二)
原文:WPF中的多进程(Threading)处理实例(二) //错误的处理 private void cmdBreakRules_Click(object sender, RoutedEventArg ...
- iOS 监听控件某个属性的改变observeValueForKeyPath
创建一个测试的UIButton #import "ViewController.h" @interface ViewController () @property(nonatomi ...
- .Net 通过Cmd执行Adb命令 /c参数
通过cmd.exe来执行adb命令,可以进行一些命令组合,直接用adb.exe的话只能执行单个adb命令 这里要注意cmd 中的/c参数,指明此参数时,他将执行整个字符串中包含的命令并退出当前cmd运 ...
- Python中实现switch分支结构
Python不像C/C++,Java等有switch-case的语法.不过其这个功能,比如用Dictionary以及lambda匿名函数特性来替代实现. 实现方法分为两步: 首先,定义一个字典: 其次 ...
- .NET框架中系列专业技术术语和缩写
CIL (Common Intermediate Language) 公共中间语言 : CIL最初是随着.NET由微软一起发布的,之前也叫MSIL(Microsoft Intermediate Lan ...
