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 ...
随机推荐
- git 的.gitignore
# vs code .vscode # Logs *.log #npm node_modules
- 674. Longest Continuous Increasing Subsequence@python
Given an unsorted array of integers, find the length of longest continuous increasing subsequence (s ...
- jwt 登录
/* eslint-disable */ 'use strict'; const Controller = require('egg').Controller; const jwt = require ...
- 【meet in middle】poj1840Eqs
震惊!map的常数居然如此之大 Description Consider equations having the following form: a1x13+ a2x23+ a3x33+ a4x43 ...
- nginx + 一个端口 部署多个单页应用(history模式)
目前web开发 使用一般前后端分离技术,并且前端负责路由.为了美观,会采用前端会采用h5 history 模式的路由.但刷新页面时,前端真的会按照假路由去后端寻找文件.此时,后端必须返回index(i ...
- linux下mysql常用的基本命令
linux数据库环境搭建好之后,我们就可以创建数据库了. 一 查看版本 mysql --version 二 进入数据库 首先在根目录执行命令 mysql -u root -p 然后输入密码 进 ...
- django 12天(跨域,文件上传,下载,cookie,session)
django 12天(跨域,文件上传,下载) 跨域 什么是跨域 1.协议不同 2.端口不同 3.主机不同 如何解决跨域 1.安装django-cors-headers模块 2.在settings.py ...
- 在 shell中, 我們可用 $0, $1, $2, $3 ... 這樣的变量分別提取命令行中变量
代码: script_name parameter1 parameter2 parameter3 ...我們很容易就能猜出 $0 就是代表 shell script 名称(路径)本身,而 $1 就是其 ...
- 自己项目使用了ARC,项目中使用第三方库继续引用ARC
Objective-C引入ARC(Automatic Reference Counting)后,我们经常会面对这样一种困境:自己的项目使用了ARC,却发现要使用的第三方类库是non-ARC的:又或者自 ...
- 组合数学的卡特兰数 TOJ 3551: Game of Connections
这个就是卡特兰数的经典问题 直接用这个公式就好了,但是这个题涉及大数的处理h(n)=h(n-1)*(4*n-2)/(n+1) 其实见过好几次大数的处理了,有一次他存的恰好不多于30位,直接分成两部分l ...