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下function声明一些小结
Dec 28 Javascript
JS简单操作select和dropdownlist实例
Nov 26 Javascript
AngularJS中$watch和$timeout的使用示例
Sep 20 Javascript
微信小程序 网络请求(GET请求)详解
Nov 16 Javascript
Node.js 数据加密传输浅析
Nov 16 Javascript
vue如何引用其他组件(css和js)
Apr 13 Javascript
详解ES6之async+await 同步/异步方案
Sep 19 Javascript
详解基于vue-cli优化的webpack配置
Nov 06 Javascript
微信小程序实现复选框效果
Dec 28 Javascript
vue-resource:jsonp请求百度搜索的接口示例
Nov 09 Javascript
解决vue单页面多个组件嵌套监听浏览器窗口变化问题
Jul 30 Javascript
解决vue数据不实时更新的问题(数据更改了,但数据不实时更新)
Oct 27 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
PHPMyadmin 配置文件详解(配置)
2009/12/03 PHP
基于PHP生成静态页的实现方法
2013/05/10 PHP
探讨多键值cookie(php中cookie存取数组)的详解
2013/06/06 PHP
php实现执行某一操作时弹出确认、取消对话框
2013/12/30 PHP
PHP 数组黑名单/白名单实例代码详解
2019/06/04 PHP
PHP session垃圾回收机制实例分析
2019/06/28 PHP
CL vs ForZe BO5 第三场 2.13
2021/03/10 DOTA
[原创]后缀就扩展名为js的文件是什么文件
2007/12/06 Javascript
javascript 处理HTML元素必须避免使用的一种方法
2009/07/30 Javascript
JS小框架 fly javascript framework
2009/11/26 Javascript
JavaScript中的闭包原理分析
2010/03/08 Javascript
JavaScript使用过程中需要注意的地方和一些基本语法
2010/08/26 Javascript
jquery实现全选、反选、获得所有选中的checkbox
2020/09/13 Javascript
AngularJs Injecting Services Into Controllers详解
2016/09/02 Javascript
Node.js的文件权限及读写flag详解
2016/10/11 Javascript
微信小程序购物商城系统开发系列-工具篇的介绍
2016/11/21 Javascript
d3.js实现立体柱图的方法详解
2017/04/28 Javascript
jQuery实现动态给table赋值的方法示例
2017/07/04 jQuery
Vue使用高德地图搭建实时公交应用功能(地图 + 附近站点+线路详情 + 输入提示+换乘详情)
2018/05/16 Javascript
解决ng-repeat产生的ng-model中取不到值的问题
2018/10/02 Javascript
详解vue-cli 2.0配置文件(小结)
2019/01/14 Javascript
Python装饰器实现几类验证功能做法实例
2017/05/18 Python
requests和lxml实现爬虫的方法
2017/06/11 Python
Python基于Pymssql模块实现连接SQL Server数据库的方法详解
2017/07/20 Python
Python单体模式的几种常见实现方法详解
2017/07/28 Python
Python中单线程、多线程和多进程的效率对比实验实例
2019/05/14 Python
python3 使用traceback定位异常实例
2020/03/09 Python
Python 实现网课实时监控自动签到、打卡功能
2020/03/12 Python
限量版运动鞋和街头服饰:TheDrop
2020/09/06 全球购物
Android面试题附答案
2014/12/08 面试题
小学生国旗下演讲稿
2014/04/25 职场文书
施工单位工程部经理岗位职责
2015/04/09 职场文书
民事申诉状范本
2015/05/20 职场文书
Python数据分析入门之教你怎么搭建环境
2021/05/13 Python
css中z-index: 0和z-index: auto的区别
2021/08/23 HTML / CSS
详解nginx安装过程并代理下载服务器文件
2022/02/12 Servers