在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 函数作用域的“提升”现象的更多相关文章

  1. 浅谈JavaScript 函数作用域当中的“提升”现象

    在JavaScript当中,定义变量通过var操作符+变量名.但是不加 var 操作符,直接赋值也是可以的. 例如 : message = "hello JavaScript ! " ...

  2. JavaScript的作用域和提升机制

    JavaScript的作用域和提升机制 你知道下面的JavaScript代码执行时会输出什么吗? 1 2 3 4 5 6 7 8 var foo = 1; function bar() {     i ...

  3. (转载)javascript函数作用域和提前声明

    http://www.cnblogs.com/ArthurPatten/p/3274080.html 一些语言如C.java都有块级作用域,即花括号内的每一段代码都具有各自的作用域,而且变量在声明它们 ...

  4. javascript函数作用域和提前声明

    一些语言如C.java都有块级作用域,即花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的,但是javascript没有块级作用域.javascript使用函数作用域,即 ...

  5. JavaScript 函数作用域和闭包

    函数作用域和闭包  词法作用域   它们在定义它们的作用域里运行,而不是在执行的作用域运行,但是只有在运行时,作用域链中的属性才被 定义(调用对象),此时,可访问任何当前的绑定.   调用对象     ...

  6. javascript函数作用域链之词法作用域

    在开发语言中常见的作用域规则有  块级作用域和词法作用域 作用域 顾名思义就是起作用的区域  定义一变量后 ,可以在此范围作用的区域 一.块级作用域就是用一个块结构分割变量的访问区域  块即{ } 代 ...

  7. javascript函数作用域实践

    在es6之前,JavaScript是没有块级作用域的,只有函数作用域,也就是说是一个function里面定义的变量外面取不到的:而if for是条件判断的语句,不是函数,由于缺少块级作用域,所以条件中 ...

  8. JavaScript函数作用域和声明提前(3.10.1 page.57)

    <h4>3.函数作用域和声明提前</h4> <p> <!--<script type="text/javascript">-- ...

  9. Javascript 函数声明先提升还是变量先提升

    大家都知道js 分为词法阶段 和执行阶段 也知道它是因为var变量和函数声明会提升 但是你知道他们两个谁先提升的吗 测试一下 function test(){ alert(4); } var test ...

随机推荐

  1. Java 的访问权限

    public>protected>默认(包访问权限)>private,因为protected除了可以被同一包访问,还可以被包外的子类所访问

  2. bzoj5138 [Usaco2017 Dec]Push a Box

    题目描述: bz luogu 题解: 暴力可以记录$AB$位置转移,这个时候状态是$n^4$的,无法接受. 考虑只记录$A$在$B$旁边时的状态,这个时候状态时$n^2$的. 所以说转移有两种,一种是 ...

  3. [LUOGU] P1111 修复公路

    题目背景 A地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车.政府派人修复这些公路. 题目描述 给出A地区的村庄数N,和公路数M,公路是双向的.并告诉你每条公路的连着哪两个村庄,并告诉你什么时 ...

  4. 【Java_多线程并发编程】基础篇——线程状态扭转函数

    1. wait() sleep() yield() join()用法与区别 本文提到的当前线程是指:当前时刻,获得CPU资源正在执行的线程. 1.1 wait()方法 wait()方法定义在Objec ...

  5. JavaWeb项目中集成Swagger API文档

    1.增加依赖 <dependency> <groupId>io.springfox</groupId> <artifactId>springfox-sw ...

  6. keypoint && DMatch

    下面单独介绍KEYPOINT 与DMatch的内在联系 std::vector<cv::Point2f> points1, points2; for (std::vector<cv: ...

  7. PAT Basic 1049

    1049 数列的片段和 给定一个正数数列,我们可以从中截取任意的连续的几个数,称为片段.例如,给定数列 { 0.1, 0.2, 0.3, 0.4 },我们有 (0.1) (0.1, 0.2) (0.1 ...

  8. OmniGraffler软件和激活码

    mac上用户画图的软件:OmniGraffler破解方法 1.激活码 Name: Appked SN: MFWG-GHEB-HYTW-CGHT-CSXU-QCNC-SXU 2.软件连接 链接: htt ...

  9. TOJ 4701 求阴影部分面积

    4701: 求阴影部分面积  本文版权归BobHuang和博客园共有,不得转载.如想转载,请联系作者,并注明出处. Time Limit(Common/Java):1000MS/3000MS     ...

  10. hdu2042

    #include <stdio.h> int main(){ int t,i,n,res; while(~scanf("%d",&t)){ while(t--) ...