关于JavaScript的词法作用域及变量提升的个人理解
关于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();
关于JavaScript的词法作用域及变量提升的个人理解的更多相关文章
- javascript中的作用域和变量提升
js的运行主要分两个阶段:js的预解析和运行,预解析阶段所有的变量声明和函数定义都会提前,但是变量的赋值不会提前.
- javascript中的变量作用域以及变量提升
在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解. 变量作用域 “一个变量的作用域表示这个变量存在的上 ...
- javascript中的变量作用域以及变量提升详细介绍
在javascript中, 理解变量的作用域以及变量提升是非常有必要的.这个看起来是否很简单,但其实并不是你想的那样,还要一些重要的细节你需要理解变量作用域 “一个变量的作用域表示这个变量存在的上下文 ...
- Javascript作用域和变量提升
下面的程序是什么结果? var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar(); 结果是10: 那么 ...
- JS 函数作用域及变量提升那些事!
虽然看了多次js函数作用域及变量提升的理论知识,但小编也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷) ...
- JS _函数作用域及变量提升
虽然看了多次js函数作用域及变量提升的理论知识,但也是一知半解~ 这几天做了几道js小题,对这部分进行了从新的理解,还是有所收获的~ 主要参考书籍: <你不知道的JavaScript(上卷)&g ...
- JS作用域、变量提升和闭包
作用域 作用域可以理解为JS引擎执行代码的时候,查找变量的规则. 从确定变量访问范围的阶段的角度,可以分为2类,词法作用域和动态作用域.js是词法作用域. 从变量查找的范围的角度,可以分为3类,全局作 ...
- JS高级. 05 词法作用域、变量名提升、作用域链、闭包
作用域 域,表示的是一个范围,作用域,就是作用范围. 作用域说明的是一个变量可以在什么地方被使用,什么地方不能被使用. 块级作用域 JavaScript中没有块级作用域 { var num = 123 ...
- JavaScript基础03——函数的作用域及变量提升
1.作用域 作用域,变量在函数内部作用的范围/区域.有函数的地方就有作用域. 2.局部作用域和全局作用域 function fn(){ var a = 1; } console.log(a); / ...
随机推荐
- Python3-for-enumerate
languages = ["C", "C++", "Perl", "Python"] for x in language ...
- Luogu P1641 [SCOI2010]生成字符串 组合数学
神仙.... 当时以为是,$x$代表$1$,$y$代表$0$,所以不能过$y=x$的路径数...结果不会... 然后康题解...ヾ(。`Д´。)竟然向右上是$1$,向右下是$0$.... 所以现在就是 ...
- java+大文件上传下载
文件上传下载,与传统的方式不同,这里能够上传和下载10G以上的文件.而且支持断点续传. 通常情况下,我们在网站上面下载的时候都是单个文件下载,但是在实际的业务场景中,我们经常会遇到客户需要批量下载的场 ...
- 彩色模型,CIE XYZ,CIE RGB
学习DIP第8天 转载请标明出处:http://blog.csdn.net/tonyshengtan,欢迎大家转载,发现博客被某些论坛转载后,图像无法正常显示,无法正常表达本人观点,对此表示很不满意. ...
- 新西达电调初始化代码,使用nodejs ffi技术调用wiringpi,代码使用typescript编写
这是我设计的F450四轴飞行器飞控代码的一部分 运行在orangepi-zero上,操作系统是armbian,思路是使用node-ffi调用wiringpi的so库与GPIO通信,然后控制端逻辑代码使 ...
- 国产手机的谷X服务
我换了个新手机,但面临了一个棘手的问题,就是原来的手机的谷X服务是用免root安装器自动安装好的,安装器找不到了.而后我发现现在的手机并没有阉割掉谷X服务,原因不详,好处不用在去一个个安装了.我装好y ...
- HTML语义化是什么?为什么要语义化?
HTML语义化HTML的语义化总结为: 用最恰当的标签来标记内容. 该如何理解呢?比如需要加入一个标题,这个标题的字体比正文的要大写,还要加粗.能够实现这种效果的方法有很多,比如用CSS样式进行渲染. ...
- ARTS打卡计划第十六周
Algorithms: https://leetcode-cn.com/problems/min-stack/submissions// Review: https://www.infoq.cn/ar ...
- msyql笔记
CREATE TABLE class ( cid int(11) NOT NULL AUTO_INCREMENT, caption varchar(32) NOT NULL, PRIMARY KEY ...
- Java如何接收前端传来的多层嵌套的复杂json串
想看问题直接解决方式,直接拉到博文底部. Spring的controller在接收前端传参的时候如果参数使用@RequestBody标注的时候 @RequestBody 则会把前端参数转为JSON的形 ...