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秘密花园】
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端