《趣说前端》— 第二篇

前言

首先我们必须清楚作用域是一个独立的概念,和语言无关。

接下来介绍词法作用域和动态作用域的基本知识。

入题

作用域是什么?

一个变量(参数)在程序中起作用的范围区域,也就是说只有在这个区域这个变量(参数)才是可见的;这个范围区域就是小生理解的作用域。

作用域模型又分为两种—— “词法作用域 & 动态作用域”。

  • 词法作用域模型下作用域链十分规矩,基本按规矩办事;

  • 动态作用域模型下作用域链比较洒脱,总能给人小惊喜;

首先说明一点 JavaScript 采用的是词法作用域。

词法作用域

词法作用域,也称静态作用域。JavaScript 的作用域在代码的编译阶段就已确定。这是一种既定的规则。

我们用一个例子解释一下:

var name='小生方勤';function consoleName(){  console.log(name);}function test(){var name='方小勤';  consoleName();}test();

这段代码会输出什么结果?结果很明显输出的是 '小生方勤'。

因为使用的是词法作用域模型,所以在函数声明的时候作用域就已经确定了。

引擎会先在 consoleName() 函数创建的作用域中查找 name 变量,并没有找到;这时引擎就会到包含 consoleName() 作用域的上一级作用域查找(也就是全局作用域) name 变量;发现全局作用域正好有 name 变量;所以输出的是 '小生方勤'。
再通过 JavaScript 的执行过程解释

JS 的执行过程分为两个阶段:

  • 编译阶段(由编译器完成)

  • 执行阶段(由引擎完成)

编译阶段

任务是翻译成可执行代码(JS 的作用域在这个阶段确定):

  • 词法分析

  • 语法分析(生成 AST)

  • 代码生成(转化 AST 成可执行代码)

执行阶段

任务是执行可执行代码(并创建执行上下文)。

那么在什么情况输出的是‘方小勤’呢?

动态作用域

动态作用域是在代码运行的时候确定的。也就是说动态作用域模型的作用域链是基于调用栈的。

如果这段代码是具有动态作用域的语言,那么输出的结果就是 - '方小勤'。

引擎会先在 consoleName() 函数创建的作用域中查找 name 变量,并没有找到;这时引擎就会到调用 consoleName() 函数的 test() 函数的作用域查找 name 变量;发现正好有 name 变量;所以输出的是 '方小勤'。

你是不是发现动态作用域的规则有点像 this 机制呢?

作用域链

在每个执行上下文的变量环境中,都包含了一个外部引用(outer),用来指向外部的执行上下文。

当一段代码使用了一个变量时,JavaScript 引擎首先会在“当前的执行上下文”中查找该变量,比如上面那段代码在查找 name 变量时,在当前的变量环境中没有查找到, JavaScript 引擎继续在 outer 所指向的执行上下文(全局执行上下文)中查找。

我们把这个查找的链条就称为作用域链。

总结一下

  • 词法作用域:作用域在写代码的时候就确定,即声明时确定;

  • 动态作用域:作用域在运行代码的时候确定,即调用时确定。
最后在声明一下 JavaScript 采用的是词法作用域。

留问题

最上方的例子应如何修改才能使程序输出 - '方小勤'。

参考

  1. 《JavaScript 高级程序设计》

  2. 《你不知道的 JavaScript》上

NOT THE END

该系列首发于同名公众号【小生方勤】,扫码关注即可订阅(可进交流群)。

©著作权归作者所有:来自51CTO博客作者mb5ff592736e0cf的原创作品,如需转载,请注明出处,否则将追究法律责任

更多相关文章

  1. 一网打尽 JavaScript 的作用域[每日前端夜话0x49]
  2. Python的容器有哪些?分别有什么作用?
  3. 正则表达式中模式修正符作用详解
  4. PHP作用域和文件夹操作示例
  5. Java Dao层的作用
  6. return关键字在php中的作用(含详解)
  7. 详解PHP死循环写法和作用
  8. 学习PHP死循环写法和作用
  9. PHP的中间件是什么?有什么作用?

随机推荐

  1. 将AngularJS、jQueryUI、Angular-Drag-Dr
  2. 我需要从jquery ajax post中撤回数据并将
  3. scrollTop到溢出滚动div中的活动元素
  4. [入门篇]Jquery读取.Net WebService Json
  5. html页面传值问题已解决
  6. 关于各种js框架的选择
  7. 使用jquery和ajax更新选项列表
  8. 阻止a标签跳转,且将a的get提交方式转化为p
  9. 将字符串数组发布到.net-core mvc
  10. 使用Rails 3.2和AJAX(非flash上传解决方