JavaScript中变量提升 Hoisting


Posted in Javascript onJuly 03, 2012

因为我在写这文章的时候,百度里找资料,找到了园友的一篇文章,写的很好,可是我写了又不想放弃,所以就在里面拿了很多东西过来!~~

[翻译]JavaScript Scoping and Hoisting

希望得到大家谅解。

一。案发现场

我们先看一段很简单的代码:

var v='Hello World'; 
alert(v);

这个没有疑问吧,弹出“Hello World”。OK,我们继续。

我们在看一段Code:

var v='Hello World'; 
(function(){ 
alert(v); 
})()

经过运行之后,我们发现,还是和我们预期的一样,弹出了“Hello World”。

好了,有意思的来了。接着在看一段下面的代码:

var v='Hello World'; 
(function(){ 
alert(v); 
var v='I love you'; 
})()

如果这个是一个面试题,面试官问你这个结果是多少?你怎么回答?

我们先看结果吧!

JavaScript中变量提升 Hoisting

结果是 undefined?和你上面自己想的一样吗?

好吧,我就不故弄玄虚了。其实,这里面隐藏了一个陷阱-----JavaScript中的变量提升(Hoisting);

二。深度剖析

现在我来解释下提升是什么意思?顾名思义,就是把下面的东西提到上面。在JS中,就是把定义在后面的东东(变量或函数)提升到前面中定义。

在解释提升之前,我们先来看一下js中的作用域(scoping)问题。

对于JavaScript新手来说scoping是最令人困惑的部分之一。事实上,不仅仅是新手,我遇到或很多有经验的JavaScript程序员也不能完全理解scoping。JavaScript的scoping如此复杂的原因是它看上去非常像C系语言的成员。请看下面的C程序:

#include <stdio.h> 
int main() { 
int x = 1; 
printf("%d, ", x); // 1 
if (1) { 
int x = 2; 
printf("%d, ", x); // 2 
} 
printf("%d\n", x); // 1 
}

这段程序的输出是1,2,1。这是因为在C系语言有块级作用域(block-level scope),当进入到一个块时,就像if语句,在这个块级作用域中会声明新的变量,这些变量不会影响到外部作用域。但是JavaScript却不是这样。在Firebug中试试下面的代码:

var x = 1; 
console.log(x); // 1 
if (true) { 
var x = 2; 
console.log(x); //2 
} 
console.log(x);// 2

在这段代码中,Firebug显示1,2,2。这是因为JavaScript是函数级作用域(function-level scope)。这和C系语言是完全不同的。块,就像if语句,并不会创建一个新的作用域。只有函数才会创建新的作用域。

对于大部分熟悉C,C++,C#或是Java的程序员来说,这是意料之外并且不被待见的。幸运的是,因为JavaScript函数的灵活性,对于这个问题我们有一个解决方案。如果你必须在函数中创建一个临时的作用域,请像下面这样做:

function foo() { 
var x = 1; 
if (x) { 
(function () { 
var x = 2; 
// some other code 
}()); 
} 
// x is still 1. 
}

这种方面确实非常灵活,它使用在任何需要创建一个临时作用域的地方,不仅仅是某个块中。但是,我强烈建议你花点时间好好理解下JavaScript scoping。它实在是非常强力,而且它也是我最喜欢的语言特性之一。如果你很好的理解了scoping,理解hoisting将会更加容易。

2.1变量提升
变量提升,很简单,就是把变量提升提到函数的top的地方。我么需要说明的是,变量提升 只是提升变量的声明,并不会把赋值也提升上来。

比如:

我们定义三个变量:

(function(){ 
var a='One'; 
var b='Two'; 
var c='Three'; 
})()

实际上它是这样子的:
(function(){ 
var a,b,c; 
a='One'; 
b='Two'; 
c='Three'; 
})()

这个时候就把变量提升了呀。

好,我们现在回到第一段code里面。为什么会报错呢?其实,根据我么根据上面变量提升原件以及js的作用域(块级作用域)的分析,得知 上面代码真正变成如下:

var v='Hello World'; 
(function(){ 
var v; 
alert(v); 
v='I love you'; 
})()

所以,才会提示说“undefined”。

从这里,我们也学习到,我们在写js code 的时候,我么需要把变量放在块级作用域的顶端,比如我在上面所举的例子:var a,b,c;。防止出现意外。

2.2 函数提升
函数提升是把整个函数都提到前面去。

在我们写js code 的时候,我们有2中写法,一种是函数表达式,另外一种是函数声明方式。我们需要重点注意的是,只有函数声明形式才能被提升。

函数声明方式提升【成功】

function myTest(){ 
foo(); 
function foo(){ 
alert("我来自 foo"); 
} 
} 
myTest();

函数表达式方式提升【失败】

function myTest(){ 
foo(); 
var foo =function foo(){ 
alert("我来自 foo"); 
} 
} 
myTest();

结果如下:

JavaScript中变量提升 Hoisting

左边报错了。没骗你。

应该到这里基本都可以弄懂了。~
呵呵。。
再次谢谢Beta Rabbit

作者:Lanny☆兰东才

Javascript 相关文章推荐
JQuery实现简单验证码提示解决方案
Dec 20 Javascript
javascript 实现简单的table排序及table操作练习
Dec 28 Javascript
JavaScript:new 一个函数和直接调用函数的区别分析
Jul 10 Javascript
使用jquery实现放大镜效果
Sep 02 Javascript
原生js实现模拟滚动条
Jun 15 Javascript
js对象浅拷贝和深拷贝详解
Sep 05 Javascript
bootstrap vue.js实现tab效果
Feb 07 Javascript
浅谈vue-cli 3.0.x 初体验
Apr 11 Javascript
DatePickerDialog 自定义样式及使用全解
Jul 09 Javascript
javascript随机变色实例代码
Oct 15 Javascript
使用Node.js实现base64和png文件相互转换的方法
Mar 11 Javascript
原生JS实现相邻月份日历
Oct 13 Javascript
JavaScript Scoping and Hoisting 翻译
Jul 03 #Javascript
jquery 中多条件选择器,相对选择器,层次选择器的区别
Jul 03 #Javascript
jquery 实现表单验证功能代码(简洁)
Jul 03 #Javascript
JavaScript中的细节分析
Jun 30 #Javascript
JavaScript中的作用域链和闭包
Jun 30 #Javascript
JavaScript中的面向对象介绍
Jun 30 #Javascript
js中判断数字\字母\中文的正则表达式 (实例)
Jun 29 #Javascript
You might like
php下利用curl判断远程文件是否存在的实现代码
2011/10/08 PHP
基于PHP实现的事件机制实例分析
2015/06/18 PHP
PHP命名空间namespace及use的简单用法分析
2018/08/03 PHP
PHP如何使用array_unshift()在数组开头插入元素
2020/09/01 PHP
js post方式传递提交的实现代码
2010/05/31 Javascript
Whatever:hover 无需javascript让IE支持丰富伪类
2010/06/29 Javascript
Javascript中判断变量是数组还是对象(array还是object)
2013/08/14 Javascript
js正则表达exec与match的区别说明
2014/01/29 Javascript
jQuery拖动div、移动div、弹出层实现原理及示例
2014/04/08 Javascript
客户端验证用户名和密码的方法详解
2016/06/16 Javascript
vue的props实现子组件随父组件一起变化
2016/10/27 Javascript
利用D3.js实现最简单的柱状图示例代码
2016/12/09 Javascript
Extjs gridpanel 中的checkbox(复选框)根据某行的条件不能选中的解决方法
2017/02/17 Javascript
js实现楼层导航功能
2017/02/23 Javascript
bootstrap table表格使用方法详解
2017/04/26 Javascript
react的滑动图片验证码组件的示例代码
2019/02/27 Javascript
js尾调用优化的实现
2019/05/23 Javascript
关于vue2强制刷新,解决页面不会重新渲染的问题
2019/10/29 Javascript
js实现图片上传到服务器和回显
2020/01/19 Javascript
Javascript如何实现扩充基本类型
2020/08/26 Javascript
跟老齐学Python之字典,你还记得吗?
2014/09/20 Python
使用python3实现操作串口详解
2019/01/01 Python
用Anaconda安装本地python包的方法及路径问题(图文)
2019/07/16 Python
python Tcp协议发送和接收信息的例子
2019/07/22 Python
Python3 venv搭建轻量级虚拟环境的步骤(图文)
2019/08/09 Python
Python配置文件处理的方法教程
2019/08/29 Python
python图片合成的示例
2020/11/09 Python
美国值得信赖的婚恋交友网站:eHarmony
2018/10/04 全球购物
初三学习决心书
2014/03/11 职场文书
汽车检测与维修专业求职信
2014/07/04 职场文书
知识就是力量演讲稿
2014/09/13 职场文书
2015年社区创卫工作总结
2015/04/21 职场文书
想要创业,那么你做好准备了吗?
2019/07/01 职场文书
Win11如何修改dns?Win11修改dns图文教程
2022/01/18 数码科技
Java实现字符串转为驼峰格式的方法详解
2022/07/07 Java/Android
Nginx代理Redis哨兵主从配置的实现
2022/07/15 Servers