JavaScript 声明提升 (hoisting)

结果是什么

先看两段代码。

代码1

JAVASCRIPT
var foo = 1; if(foo){ var foo = 10; } alert(foo);

结果是显而易见的,就是 10.

分析:JavaScript 会自动忽略对同一变量的重复声明,即一开始用"var foo"声明了变量foo,后面的if语句中的"var foo"会被忽略掉。但后面的初始化语句则会覆盖前面的,故foo最终被赋值为 10.

这没有任何让人困惑的地方。

代码2

JAVASCRIPT
var foo = 1; function bar() { if (!foo) { var foo = 10; } alert(foo); } bar();

结果有点奇怪——依然是 10.

这其实是 JavaScript 语言一个强大但让人困惑的特性——声明提升,有人称之为 hoisting.

先来明确一下"声明"和"初始化"的概念。

声明与初始化

在 JavaScript 中,使用一个变量时一般都会进行声明和初始化的操作。

声明

使用var操作符,后跟变量名(即一个标识符),可以定义一个变量,这便是变量的"声明"。如:

JAVASCRIPT
var name;

初始化

给一个变量赋值,即为"初始化"。如:

JAVASCRIPT
name = 'Sky';

变量的声明和初始化可以写在同一条语句中:

JAVASCRIPT
var name = 'Sky';

只声明而没有进行初始化的变量,会保存一个特殊的值undefined

明确了这两个概念后,再来看什么是声明提升。

声明提升

JavaScript 引擎在处理函数代码时,会先做这样一个隐藏操作:

函数内部的所有声明(包括声明变量、用函数声明定义一个函数等),会全部提升到函数内部的最前端,而相应的初始化语句不受影响。

上面的代码2,其实等价于这样:

JAVASCRIPT
var foo = 1; function bar() { var foo; if (!foo) { foo = 10; } alert(foo); } bar();

这样看起来就清晰多了。

带来的启示

显然,这不是一个受人欢迎的特性——它使人困惑,还很容易给代码引入 bug。

那么,我们需要做的就是,在函数的顶部便声明好需要用到的所有变量,而不要在函数的各处随意声明变量。

不要这样写:

JAVASCRIPT
function test(){ for(var i = 0; i < arguments.length; i++){ //其它代码 } }

改成这样,形成良好的编码习惯:

JAVASCRIPT
function test(){ //所有声明都统一放在顶部 var i = 0; len = arguments.length; for(; i < len; i++){ //其它代码 } }

参考

JavaScript Scoping and Hoisting

【END】

本文链接:

版权声明:本博客所有文章除声明转载外,均采用 BY-NC-SA 3.0 许可协议。转载请注明来自 iBlog

阅读 215 | 发布于 2015-11-11
暂无评论