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的函数
Jan 31 Javascript
Jquery 插件学习实例1 插件制作说明与tableUI优化
Apr 02 Javascript
基于jquery的一行代码轻松实现拖动效果
Dec 28 Javascript
JS创建类和对象的两种不同方式
Aug 08 Javascript
JS获取iframe中marginHeight和marginWidth属性的方法
Apr 01 Javascript
使用JavaScript制作一个简单的计数器的方法
Jul 07 Javascript
javascript实现动态表头及表列的展现方法
Jul 14 Javascript
JavaScript中cookie工具函数封装的示例代码
Oct 11 Javascript
详解vantUI框架在vue项目中的应用踩坑
Dec 06 Javascript
Vue入门学习笔记【基本概念、对象、过滤器、指令等】
Apr 13 Javascript
javascript+HTML5 canvas绘制时钟功能示例
May 15 Javascript
Vue项目结合Vue-layer实现弹框式编辑功能(实例代码)
Mar 11 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
从零开始的异世界生活:第二季延期后,B站上架了第二部剧场版
2020/05/06 日漫
支持php4、php5的mysql数据库操作类
2008/01/10 PHP
解析thinkphp基本配置 convention.php
2013/06/18 PHP
php实现对两个数组进行减法操作的方法
2015/04/17 PHP
php提交表单时保留多个空格及换行的文本样式的方法
2017/06/20 PHP
js 表格隔行颜色
2009/12/02 Javascript
javascript 三种编解码方式
2010/02/01 Javascript
javascript实现的使用方向键控制光标在table单元格中切换
2010/11/17 Javascript
可在线编辑网页文字效果代码(单击)
2013/03/02 Javascript
JS实现跟随鼠标闪烁转动色块的方法
2015/02/26 Javascript
JQuery判断radio(单选框)是否选中和获取选中值方法总结
2015/04/15 Javascript
20行JS代码实现网页刮刮乐效果
2017/06/23 Javascript
JavaScript HTML DOM 元素 (节点)新增,编辑,删除操作实例分析
2020/03/02 Javascript
Vue组件为什么data必须是一个函数
2020/06/11 Javascript
[02:32]DOTA2完美大师赛场馆静安体育中心观赛全攻略
2017/11/08 DOTA
[10:18]2018DOTA2国际邀请赛寻真——Fnatic能否笑到最后?
2018/08/14 DOTA
[00:37]食人魔魔法师轮盘吉兆顺应全新至宝将拥有额外款式
2019/12/19 DOTA
python中threading超线程用法实例分析
2015/05/16 Python
实例Python处理XML文件的方法
2015/08/31 Python
TensorFlow平台下Python实现神经网络
2018/03/10 Python
在Python中输入一个以空格为间隔的数组方法
2018/11/13 Python
解决python xlrd无法读取excel文件的问题
2018/12/25 Python
Python Gluon参数和模块命名操作教程
2019/12/18 Python
Python字符串的修改方法实例
2019/12/19 Python
css3如何绘制一个圆圆的loading转圈动画
2018/01/09 HTML / CSS
CSS3实现图片抽屉式效果的示例代码
2019/11/06 HTML / CSS
韩国三大免税店之一:THE GRAND 中文免税店
2016/07/21 全球购物
大学学习计划书范文
2014/05/02 职场文书
医德医风个人总结
2015/02/28 职场文书
MBA推荐信怎么写
2015/03/25 职场文书
2015年“7.11”世界人口日宣传活动方案
2015/05/06 职场文书
儿子满月酒致辞
2015/07/29 职场文书
课文《燕子》教学反思
2016/02/17 职场文书
导游词幽默开场白
2019/06/26 职场文书
python 学习GCN图卷积神经网络
2022/05/11 Python
Redis 限流器
2022/05/15 Redis