JavaScript 函数作用域的“提升”现象
在JavaScript当中,定义变量通过var操作符+变量名。但是不加 var 操作符,直接赋值也是可以的。
例如 : message = "hello JavaScript ! " 即定义了一个全局变量message,并赋值 “Hello JavaScript!”
--《JavaScript高级程序第三版》
如同往日一般,一群人在所谓的技术交流群里面相互斗图着。突然老王莫名的正经起来,在群里发了一道JavaScript的题目,让大家猜一猜这道题的答案。
var foo = 1;
function bar() {
foo = 10;
return;
function foo() {}
}
bar();
console.log(foo); //求控制台输出多少?
看到这到题目之后,立刻不加思索回答了“10”。
首先第一步定义一个全局变量foo = 1
,然后函数执行的时候又定义全局变量 foo = 10
覆盖了之前的全局变量,return之后,这个函数就直接结束, function foo {}
来不及定义。因此控制台输出10;
按照在《高三》上面看到知识点推断,毫无问题,简直完美呀!
【给自己32个赞!】
但是,在把答案发出去之后。本能就感觉这道题不可能这么简单,不正经的群突然讨论正经的代码,肯定会有大坑等着人来跳。一种不好感觉涌上心头,感觉自己又要被打脸了。
赶紧打开编辑器测试一下这段代码,手哆嗦的按下F12.只见控制台下,一个耀眼的1赫然闯入眼帘。啪啪啪!!这脸又被打的,好疼呀!!
【为什么被打脸的总是我!!】
果不其然群里老王马上的在群里否决我的答案,啪的一下打了这张老脸。
不行!这个脸打了得把场子找回来,这个老王接下来肯定会揭晓答案并公布解题思路。得在他公布之前,讲答案和原因给测试出来。
经过简单的测试之后,发现原来是后面的foo,函数提升到最顶端了。所以后面foo = 10
中的foo实际上是一个局部变量了。因此后面console.log(foo)
时是拿不到bar函数中的局部变量foo = 10
,因此只能拿到全局变量foo = 1;所以控制台输出1。
上文代码的另外一种形式:
var foo = 1;
function bar() {
function foo(){}
foo = 10;
return;
// function foo() {} 相当于这行代码提升到最顶部了
}
bar();
console.log(foo);
被抢了风头的老王果断的不服气呀!说我瞎猜扯犊子一厢情愿的,自己随意猜想的。
好的,下面就是开始解释我为什么说函数function foo(){}
提升到最顶端。不改动老王的代码,让我们只是加两个console.log
测试一下相应的输出结果。
var foo = 1;
console.log("全局变量:foo = " + window.foo)
function bar() {
console.log("此时bar函数中foo =" + foo)
foo = 10;
console.log("bar函数中的变量是" + foo);
console.log("全局变量foo还是:"+window.foo);
return;
function foo() {}
}
bar();
console.log(foo);
浏览器输出结果
通过这里可以证实我的猜想是正确的,function foo(){}
直接被提升到bar()函数最顶端,然后后面foo = 10
就不是再重新定义全局变量了,这里foo是一个局部变量的角色被定义出现的。因此才没有将全局变量给覆盖,而由于函数外面是不能直接拿到bar函数当中的局部变量foo,因此继续向上寻找到全局变量foo = 1.从而输出1.
这里估计联想能力丰富的小伙伴肯定会举手说,那么函数有提升的现象。那么变量也是否会有提升现象?不错!不错!!这位小伙伴联想的非常正确,学习就要多学会举一反三。
【奖励一朵小红花】
变量提升
var foo = 1;
function bar() {
foo = 10;
return;
var foo //几乎是相同的代码,只是把 function foo 变成了 var foo。变量也是能够提升了的!
}
bar();
console.log(foo); //还是输出1.
思考:
同样的既然变量能够提升,函数声明能够提升。那么谁升的更高呢?
function test(){
console.log(dabang);
function dabang(){};
var dabang;
}
test();
function test1(){
console.log(dabang);
var dabang;
function dabang(){};
}
test1();
控制台输出结果:
【大棒声明的函数那必须升的高!!!】
小结:
1、在JavaScript当中,函数作用域当中。变量和声明函数都能够提升。
2、同样提升的情况下,声明函数提升的更加高!
以上就是鄙人对于JavaScript函数作用域中“提升现象”一点简单理解,欢迎各位的大佬们指导学习。
其实js的编译就是把作用域先声明,作用域里面用到变量统一先在代码执行前分配内存,也就是先声明,function a(){}这个就直接声明了a函数,var a=function(){}这个表达式是在执行前先声明a变量值为undefined,执行到这句才把function赋值进去.
JavaScript 函数作用域的“提升”现象的更多相关文章
- 浅谈JavaScript 函数作用域当中的“提升”现象
在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的. 例如 : message = "hello JavaScript ! " ...
- JavaScript的作用域和提升机制
JavaScript的作用域和提升机制 你知道下面的JavaScript代码执行时会输出什么吗? 1 2 3 4 5 6 7 8 var foo = 1; function bar() { i ...
- (转载)javascript函数作用域和提前声明
http://www.cnblogs.com/ArthurPatten/p/3274080.html 一些语言如C.java都有块级作用域,即花括号内的每一段代码都具有各自的作用域,而且变量在声明它们 ...
- javascript函数作用域和提前声明
一些语言如C.java都有块级作用域,即花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的,但是javascript没有块级作用域.javascript使用函数作用域,即 ...
- JavaScript 函数作用域和闭包
函数作用域和闭包 词法作用域 它们在定义它们的作用域里运行,而不是在执行的作用域运行,但是只有在运行时,作用域链中的属性才被 定义(调用对象),此时,可访问任何当前的绑定. 调用对象 ...
- javascript函数作用域链之词法作用域
在开发语言中常见的作用域规则有 块级作用域和词法作用域 作用域 顾名思义就是起作用的区域 定义一变量后 ,可以在此范围作用的区域 一.块级作用域就是用一个块结构分割变量的访问区域 块即{ } 代 ...
- javascript函数作用域实践
在es6之前,JavaScript是没有块级作用域的,只有函数作用域,也就是说是一个function里面定义的变量外面取不到的:而if for是条件判断的语句,不是函数,由于缺少块级作用域,所以条件中 ...
- JavaScript函数作用域和声明提前(3.10.1 page.57)
<h4>3.函数作用域和声明提前</h4> <p> <!--<script type="text/javascript">-- ...
- Javascript 函数声明先提升还是变量先提升
大家都知道js 分为词法阶段 和执行阶段 也知道它是因为var变量和函数声明会提升 但是你知道他们两个谁先提升的吗 测试一下 function test(){ alert(4); } var test ...
随机推荐
- iOS7.1企业版发布后用户通过sarafi浏览器安装无效的解决方案
关于iOS7.1企业版发布后,用户通过sarafi浏览器安装无效的解决方案: 通过测试,已经完美解决. 方案一: iOS7.1企业应用无法安装应用程序 因为证书无效的解决方案 http://blog. ...
- How To:Linux下如何通过命令检查网卡是否插上网线
主要工具为ethtool来检查,主要关注的字段为"Link detected",注意如下的输出,其中em4实际物理上并未插上网线,而em1是插上网线的: # ethtool em4 ...
- 51nod 1135 原根 (数论)
题目链接 建议与上一篇欧拉函数介绍结合食用. 知识点:1.阶:a和模m互质,使a^d≡1(mod m)成立的最小正整数d称为a对模m的阶(指数) 例如: 2^2≡1(mod3),2对模3的阶为2; ...
- 使用Spring Cloud需要了解一些概念
Spring Cloud是一个基于Spring Boot实现的微服务架构开发工具,它为基于JVM的微服务开发中的配置管理.服务发现.断路器.智能路由.微代理.控制总线.全局锁.决策竞选.分布式会话和集 ...
- perl学习二:简单变量
字符串变量:${}1.单引号:不进行变量替换,不进行转义,字符串可以跨行.2.双引号:变量替换(贪婪匹配原则).支持转义字符(转义字符可以另外看)3.反引号 字符串的特殊表示方法:qq(...) q( ...
- Django 连接mysql数据库
首先在settings.py文件里将 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.pat ...
- stm32L011F3——串口实例
/* STM32L0xx HAL library initialization: - Configure the Flash prefetch, Flash preread and Buffer ca ...
- PYDay4-基本数据类型、字符串、元组、列表、字典
1.关于编码: utf-8 与gbk都是对Unicode 编码的简化,utf-8是针对所有语言的精简,gbk是针对中文的精简 py3默认字符集为UTF-8,取消了Unicode字符集,如后面的编程过程 ...
- NYOJ 814 又见拦截导弹
又见拦截导弹 时间限制:3000 ms | 内存限制:65535 KB 难度:3 描述 大家对拦截导弹那个题目应该比较熟悉了,我再叙述一下题意:某国为了防御敌国的导弹袭击,新研制出来一种导弹拦 ...
- HDU-4847 Wow! Such Doge!,模拟!
Wow! Such Doge! 题意:给定的字符串中doge出现了多少次,直接模拟即可,不用KMP. char s[N]; int main() { // int n; int ans=0; whil ...