关于JavaScript的作用域,最近听到一个名词:“词法作用域”;以前没有听说过(读书少),记录一下对此的理解,加深印象。

词法作用域:在JavaScript中,一个函数的作用域,在这个函数定义好的时候就决定好了;因此判断该函数的上一级作用域,不是看函数在哪里调用,而是看函数在哪里编写;请勿和this进行混淆了

第1个例子:

 function fn(callback){
var age=18;
callback()
} fn(function(){
console.log(age) // 此处会输出什么结果?
})

分析:在第3行代码调用匿名函数时,会在匿名函数的作用域范围内查找age变量,此时的作用域是找不到age变量的;所以会查找匿名函数的上一级,重点是该匿名函数的上一级作用域是什么?好,下面在看一个例子。

第2个例子:

 function fn(cb){
var age=18;
cb()
} function callback(){
console.log(age) // 此处会输出什么结果?
} fn(callback);

分析:第二个例子相对于第一个列子来说,只是把匿名函数改成了callback函数而已。由第二个例子可以很明确的看出,callback函数的上一级作用域其实是全局作用域,即是window;在callback函数的作用域内,找不到age变量;因此需要网上一级查找,在全局作用域window中也找不到age变量,所以,以上两个例子的输出结果都是报以下的错误:

总结:由上面的两个例子可以看出,在JavaScript中,判断一个函数的上一级作用域是什么?需要看这个函数时在哪个作用域中声明的,而不是在哪个作用域调用的;这就是JavaScript的词法作用域。

 第3个例子:

 var x = "globol value";
function getValue(){
console.log(x); // 此处会输出什么?
var x = "local value";
console.log(x); // 此处会出输出什么?
}
getValue();

分析:按照前面两个例子的词法作用域进行分析,getValue函数是在全局作用域window中编写的,所以是可以访问到window作用域的x变量的,按理来说,输出的结果应该会是:“globol value”和“local value”的;但是,在ES6之前,使用var声明的变量,会存在变量提升即将变量声明提升到它所在作用域的最开始的部分,类似于函数声明提升( function declaration hoisting);因此第3个例子可以改写为如下代码:

 var x = "globol value";
function getValue(){
var x; // 声明变量,不进行赋值,默认值为undefined
console.log(x);
x = "local value";
console.log(x);
}
getValue();

所以,第3个例子输出的结果是:undefined和“local value”;如果想要输出“globol value”和“local value”,那么可以改为如下代码:

 var x = "globol value";
function getValue(){
console.log(window.x);
var x = "local value";
console.log(x);
}
getValue();

PS:在ES6中,如果使用let和const关键字来声明变量,是不会存在变量提升的效果的。有兴趣的朋友可以执行一下以下的代码,看看是什么效果,要理解下面这个例子的结果,可以去看看阮一峰老师的关于let的暂时性死区的阐述:http://es6.ruanyifeng.com/#docs/let

 var x = "globol value";
function getValue(){
console.log(x);
let x = "local value";
console.log(x);
}
getValue();

最新文章

  1. ios 生成问题
  2. 转:windows命令行下如何查看磁盘空间大小
  3. 浅谈我的编程之路——感谢引领我的leader
  4. HDU 3016 线段树区间更新+spfa
  5. 021ARM处理器工作模式
  6. Environment 类
  7. 解决:cc1.exe: sorry, unimplemented: 64-bit mode not compiled in
  8. Andy's First Dictionary
  9. css优先级机制说明
  10. BodyContent揭秘及定制复杂的JSP标签
  11. JDBC访问数据库
  12. 如何添加title左侧的图标
  13. 使用vmimeNET解析账单邮件
  14. import tensorflow 报错: tf.estimator package not installed.
  15. python内置函数zip
  16. 利用order by 进行盲注
  17. mariadb 10.1查看per connection内存消耗
  18. Linux/Unix分配进程ID的方法以及源代码实现
  19. [Erlang22]如何按规则位数输出数字
  20. N个富文本编辑器/基于Web的HTML编辑器

热门文章

  1. httpclient发邮件
  2. 题解 [51nod1385] 凑数字
  3. Can't install '*' from pristine store, because no checksum is recorded for this file
  4. 03 JavaScript的使用
  5. http method
  6. WM_PAINT(父子窗口间)
  7. js中的时间显示
  8. Codeforces 1106E. Lunar New Year and Red Envelopes(DP)
  9. Python控制台输出时刷新当前行内容而不是输出新行
  10. Linux设备驱动程序 之 度量时间差