Javascript变量声明的提升(Hosting) 【摘】

进入正题之前让我们先看一段简单的代码:
bar("bar"); //运行结果:undefined
var bar = function (data) { alert(data); }; //用函数字面量(Function Literals)声明函数

test("aaa"); //运行结果:aaa
function test(data) { alert(data); } //用函数关键字声明函数

(如果对函数声明方式有疑惑,请访问http://dancewithnet.com/2008/05/07/javascript-anonymous-function/)

以上两种方式都是在声明函数之前调用了它,但为什么后者能正确输出预期结果,而前者却是undefined呢? 这就涉及到了JS中变量声明提升的问题,请见下文:


Javascript变量声明的提升(Hosting)
javascript会提升变量的声明。这意味着var表达式和function声明都会被提升到当前作用域的顶部。

上面的代码在运行之前将被转化,Javascript会把var表达式和function声明提升到当前作用域的顶部,如下:

var bar;
function test(data) { alert(data); }

bar("bar");
bar = function (data) { alert(data); };
test("aaa");

可以得出结论:函数bar在声明前确实被调用了,而函数test却因为变量声明提升的特性先被移到了作用域顶部进行了声明,然后才调用的,所以能正确输出结果。

---------------------------------惨无人道的分割线-------------------------------------------------------
下面再来看一个例子:
bar();
var bar = function () { };
var someValue = 42;
test();
function test(data) {
    if (false) {
        goo = 1;
    } else {
        var goo = 2;
    }
    for (var i = 0; i < 100; i++) {
        var e = data[i];
    }
}
上面代码在运行之前将会被转化。JavaScript将会把var 表达式和function 声明提升到当前作用域的顶部。
// var表达式被移动到这里
var bar, someValue; //缺省值是'undefined'
//函数声明也会提升
function test(data) {
    var goo, i, e; // 没有块级作用域,这些变量被移动到函数顶部
    if (false) {
        goo = 1;
    } else {
        goo = 2;
    }
    for (i = 0; i < 100; i++) {
        e = data[i];
    }
}
bar(); //出错:TypeError,因为bar依然是'undefined'
someValue = 42; // 赋值语句不会被提升规则(hoisting)影响
bar = function () { };
test();

没有块级作用域不仅导致var 表达式被从循环内移到外部,而且使一些if 表达式更难看懂。
在原来代码中,if 表达式看起来修改了全部变量goo,实际上在提升规则被应用后,却是在修改局部变量。

---------------------------------灭绝人寰的分割线-------------------------------------------------------
如果没有提升规则(hoisting)的知识,下面的代码看起来会抛出异常ReferenceError。
//检查SomeImportantThing是否已经被初始化
if (!SomeImportantThing) {
    var SomeImportantThing = {};
}
实际上,上面的代码正常运行,因为var 表达式会被提升到全局作用域的顶部。
var SomeImportantThing;
if (!SomeImportantThing) {
    SomeImportantThing = {};
}

---------------------------------藐视一切的分割线-------------------------------------------------------
在Nettuts+网站有一篇介绍hoisting的文章,其中的代码很有启发性。
var myvar = "my value";
(function () {
    alert(myvar); //undefined
    var myvar="local value";
})();
输出了undefined,有些费解吗?那我们把它按照提升规则进行拆分,如下:
var myvar = "my value";
function test() {
    var myvar; //局部变量
    alert(myvar); //赋值前输出了
    myvar = "local value";
};
test();
这下结果就明朗了吧!
本文内容来自【Javascript秘密花园】

posted @   skybirdzw  阅读(104)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
点击右上角即可分享
微信分享提示