深入理解javascript作用域第二篇之词法作用域和动态作用域


Posted in Javascript onJuly 24, 2016

前面的话

大多数时候,我们对作用域产生混乱的主要原因是分不清楚应该按照函数位置的嵌套顺序,还是按照函数的调用顺序进行变量查找。再加上this机制的干扰,使得变量查找极易出错。这实际上是由两种作用域工作模型导致的,作用域分为词法作用域和动态作用域,分清这两种作用域模型就能够对变量查找过程有清晰的认识。本文是深入理解javascript作用域系列第二篇——词法作用域和动态作用域

词法作用域

第一篇介绍过,编译器的第一个工作阶段叫作分词,就是把由字符组成的字符串分解成词法单元。这个概念是理解词法作用域的基础

简单地说,词法作用域就是定义在词法阶段的作用域,是由写代码时将变量和块作用域写在哪里来决定的,因此当词法分析器处理代码时会保持作用域不变

关系

无论函数在哪里被调用,也无论它如何被调用,它的词法作用域都只由函数被声明时所处的位置决定

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三个变量的引用。它首先从最内部的作用域,也就是bar(...)函数的作用域开始查找。引擎无法在这里找到a,因此会去上一级到所嵌套的foo(...)的作用域中继续查找。在这里找到了a,因此引擎使用了这个引用。对b来讲也一样。而对c来说,引擎在bar(...)中找到了它

[注意]词法作用域查找只会查找一级标识符,如果代码引用了foo.bar.baz,词法作用域查找只会试图查找foo标识符,找到这个变量后,对象属性访问规则分别接管对bar和baz属性的访问

foo = {
bar:{
baz: 1
}
};
console.log(foo.bar.baz);//1

遮蔽

作用域查找从运行时所处的最内部作用域开始,逐级向外或者说向上进行,直到遇见第一个匹配的标识符为止

在多层的嵌套作用域中可以定义同名的标识符,这叫作“遮蔽效应”,内部的标识符“遮蔽”了外部的标识符

var a = 0;
function test(){
var a = 1;
console.log(a);//1
}
test();

全局变量会自动为全局对象的属性,因此可以不直接通过全局对象的词法名称,而是间接地通过对全局对象属性的引用来对其进行访问

var a = 0;
function test(){
var a = 1;
console.log(window.a);//0
}
test();

通过这种技术可以访问那些被同名变量所遮蔽的全局变量。但非全局的变量如果被遮蔽了,无论如何都无法被访问到

动态作用域

javascript使用的是词法作用域,它的最重要的特征是它的定义过程发生在代码的书写阶段

那为什么要介绍动态作用域呢?实际上动态作用域是javascript另一个重要机制this的表亲。作用域混乱多数是因为词法作用域和this机制相混淆,傻傻分不清楚

动态作用域并不关心函数和作用域是如何声明以及在任何处声明的,只关心它们从何处调用。换句话说,作用域链是基于调用栈的,而不是代码中的作用域嵌套

var a = 2;
function foo() {
console.log( a );
}
function bar() {
var a = 3;
foo();
}
bar();

【1】如果处于词法作用域,也就是现在的javascript环境。变量a首先在foo()函数中查找,没有找到。于是顺着作用域链到全局作用域中查找,找到并赋值为2。所以控制台输出2

【2】如果处于动态作用域,同样地,变量a首先在foo()中查找,没有找到。这里会顺着调用栈在调用foo()函数的地方,也就是bar()函数中查找,找到并赋值为3。所以控制台输出3

小结:两种作用域的区别,简而言之,词法作用域是在定义时确定的,而动态作用域是在运行时确定的

以上所述是小编给大家介绍的深入理解javascript作用域第二篇之词法作用域和动态作用域,希望对大家有所帮助,如果大家想了解更多内容敬请关注三水点靠木!

Javascript 相关文章推荐
js 单引号 传递方法
Jun 22 Javascript
让你的博客飘雪花超出屏幕依然看得见
Jan 04 Javascript
解析javascript 实用函数的使用详解
May 10 Javascript
javascript的动态加载、缓存、更新以及复用(一)
Jun 09 Javascript
快速掌握Node.js中setTimeout和setInterval的使用方法
Mar 21 Javascript
使用jquery给新生的th绑定hover事件的实例
Feb 10 Javascript
详解Webpack+Babel+React开发环境的搭建的方法步骤
Jan 09 Javascript
vue-router 组件复用问题详解
Jan 22 Javascript
基于vue2.x的电商图片放大镜插件的使用
Jan 22 Javascript
Vue中的v-for指令不起效果的解决方法
Sep 27 Javascript
node.js中express模块创建服务器和http模块客户端发请求
Mar 06 Javascript
vue实现移动端div拖动效果
Mar 03 Vue.js
关于input全选反选恶心的异常情况
Jul 24 #Javascript
JS中的==运算: [''] == false —>true
Jul 24 #Javascript
JavaScript关于提高网站性能的几点建议(一)
Jul 24 #Javascript
JavaScript提高网站性能优化的建议(二)
Jul 24 #Javascript
JavaScript学习小结之使用canvas画“哆啦A梦”时钟
Jul 24 #Javascript
省市二级联动小案例讲解
Jul 24 #Javascript
基于jQuery实现多标签页切换的效果(web前端开发)
Jul 24 #Javascript
You might like
php discuz 主题表和回帖表的设计
2009/03/13 PHP
PHP把空格、换行符、中文逗号等替换成英文逗号的正则表达式
2014/05/04 PHP
Zend Framework教程之前端控制器Zend_Controller_Front用法详解
2016/03/07 PHP
Yii框架批量插入数据扩展类的简单实现方法
2017/05/23 PHP
利用Ext Js生成动态树实例代码
2008/09/08 Javascript
PNG背景在不同浏览器下的应用
2009/06/22 Javascript
javascript 进阶篇3 Ajax 、JSON、 Prototype介绍
2012/03/14 Javascript
javascript中的startWith和endWith的几种实现方法
2013/05/07 Javascript
javascript上传图片前预览图片兼容大多数浏览器
2013/10/25 Javascript
JavaScript异步编程Promise模式的6个特性
2014/04/03 Javascript
JQuery插件iScroll实现下拉刷新,滚动翻页特效
2014/06/22 Javascript
jQuery实现TAB风格的全国省份城市滑动切换效果代码
2015/08/24 Javascript
从零学习node.js之详解异步控制工具async(八)
2017/02/27 Javascript
javascript算法之二叉搜索树的示例代码
2017/09/12 Javascript
vue单文件组件lint error自动fix与styleLint报错自动fix详解
2019/01/08 Javascript
个人小程序接入支付解决方案
2019/05/23 Javascript
[46:47]2014 DOTA2国际邀请赛中国区预选赛 DT VS HGT
2014/05/22 DOTA
用Python脚本生成Android SALT扰码的方法
2013/09/18 Python
在Python中操作字符串之replace()方法的使用
2015/05/19 Python
一个基于flask的web应用诞生 组织结构调整(7)
2017/04/11 Python
python实现FTP服务器服务的方法
2017/04/11 Python
将字典转换为DataFrame并进行频次统计的方法
2018/04/08 Python
python调用xlsxwriter创建xlsx的方法
2018/05/03 Python
Python3中exp()函数用法分析
2019/02/19 Python
Python简单实现区域生长方式
2020/01/16 Python
详解HTML5新增标签
2017/11/27 HTML / CSS
美国学校校服,儿童和婴儿服装:Cookie’s Kids
2016/10/14 全球购物
如何设置Java的运行环境
2013/04/05 面试题
电子商务网站的创业计划书
2014/01/05 职场文书
初中生自我鉴定
2014/02/04 职场文书
劳动竞赛活动方案
2014/02/20 职场文书
小学班长竞选演讲稿
2014/04/24 职场文书
心理咨询承诺书
2014/05/20 职场文书
销售内勤岗位职责
2015/02/10 职场文书
入党积极分子群众意见
2015/06/01 职场文书
只需要12页,掌握撰写一流商业计划书的技巧
2019/05/07 职场文书