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 相关文章推荐
javascript eval函数深入认识
Feb 21 Javascript
jQuery语法高亮插件支持各种程序源代码语法着色加亮
Apr 27 Javascript
分享JavaScript获取网页关闭与取消关闭的事件
Dec 13 Javascript
js制作简易年历完整实例
Jan 28 Javascript
JavaScript中的this关键字使用详解
Aug 14 Javascript
js学习阶段总结(必看篇)
Jun 16 Javascript
JS取数字小数点后两位或n位的简单方法
Oct 24 Javascript
图解Javascript——作用域、作用域链、闭包
Mar 21 Javascript
js模拟百度模糊搜索的实例
Aug 04 Javascript
Vue中的ref作用详解(实现DOM的联动操作)
Aug 21 Javascript
mongodb初始化并使用node.js实现mongodb操作封装方法
Apr 02 Javascript
vue  elementUI 表单嵌套验证的实例代码
Nov 06 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 session
2013/10/28 PHP
IE innerHTML,outerHTML所引起的问题
2009/06/04 Javascript
JavaScript学习历程和心得小结
2010/08/16 Javascript
javascript之querySelector和querySelectorAll使用介绍
2011/12/20 Javascript
js onload处理html页面加载之后的事件
2013/10/30 Javascript
js 剪切板应用clipboardData详细解析
2013/12/17 Javascript
JS获取随机数函数可自定义最小值最大值
2014/05/08 Javascript
js使用栈来实现10进制转8进制与取除数及余数
2014/06/11 Javascript
js判断浏览器类型为ie6时不执行
2014/06/15 Javascript
jquery搜索框效果实现方法
2015/01/16 Javascript
javascript二维数组转置实例
2015/01/22 Javascript
jQuery匹配文档链接并添加class的方法
2015/06/26 Javascript
基于jQuery实现以手风琴方式展开和折叠导航菜单
2016/01/28 Javascript
jQuery得到多个值只能用取Class ,不能用取ID的方法
2016/12/04 Javascript
nodejs实例解析(输出hello world)
2017/01/03 NodeJs
ThinkPHP+jquery实现“加载更多”功能代码
2017/03/11 Javascript
浅析JavaScript中的平稳退化(graceful degradation)
2017/07/24 Javascript
JavaScript实现动态添加Form表单元素的方法示例
2017/08/14 Javascript
JS中的回调函数实例浅析
2018/03/21 Javascript
Vue 实现展开折叠效果的示例代码
2018/08/27 Javascript
Vue+Element实现表格编辑、删除、以及新增行的最优方法
2019/05/28 Javascript
es6中Promise 对象基本功能与用法实例分析
2020/02/23 Javascript
Vue CLI4 Vue.config.js标准配置(最全注释)
2020/06/05 Javascript
基于原生js实现判断元素是否有指定class名
2020/07/11 Javascript
[38:21]2018DOTA2亚洲邀请赛3月30日 小组赛A组 LGD VS Newbee
2018/03/31 DOTA
pycharm+PyQt5+python最新开发环境配置(踩坑)
2019/02/11 Python
简单介绍django提供的加密算法
2019/12/18 Python
python GUI库图形界面开发之PyQt5多线程中信号与槽的详细使用方法与实例
2020/03/08 Python
Python使用文件操作实现一个XX信息管理系统的示例
2020/07/02 Python
python如何快速拼接字符串
2020/10/28 Python
入党申请人的自我鉴定
2013/12/01 职场文书
技术岗位竞聘演讲稿
2014/05/16 职场文书
2014年纳税评估工作总结
2014/12/23 职场文书
2015年计生工作总结范文
2015/04/24 职场文书
争做文明公民倡议书
2019/06/24 职场文书
Python selenium的这三种等待方式一定要会!
2021/06/10 Python