网上找了两个经典的例子
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar(); // 10
var a = 1;
function b() {
a = 10;
return;
function a() {}
}
b();
alert(a);// 1
在JavaScript中,函数、变量的声明都会被提升(hoisting)到该函数或变量所在的scope的顶部。即——JavaScript的变量提升。
javascript中一个名字(name)以四种方式进入作用域(scope),其优先级顺序如下:
- 语言内置:所有的作用域中都有 this 和 arguments 关键字;
- 形式参数:函数的参数在函数作用域中都是有效的;
- 函数声明:形如function foo() {};
- 变量声明:形如var bar;
名字声明的优先级如上所示。也就是说如果一个变量的名字与函数的名字相同,那么函数的名字会覆盖变量的名字,无论其在代码中的顺序如何。但名字的初始化却是按其在代码中书写的顺序进行的,不受以上优先级的影响。
(function(){
var foo;
console.log(typeof foo); //function
function foo(){}
foo = "foo";
console.log(typeof foo); //string
var foo;
})();
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
变量的提升(Hoisting)只是其定义提升,而变量的赋值并不会提升。
再来看一个例子,下面两段代码其实是等价的:
function foo() {
if (false) {
var x = 1;
}
return;
var y = 1;
}
function foo() {
var x, y;
if (false) {
x = 1;
}
return;
y = 1;
}
创建一个函数的方法有两种:
一种是通过函数声明function foo(){}
另一种是通过定义一个变量var foo = function(){}
function test() {
foo(); // TypeError "foo is not a function"
bar(); // "this will run!"
var foo = function () { // function expression assigned to local variable 'foo'
alert("this won't run!");
}
function bar() { // function declaration, given the name 'bar'
alert("this will run!");
}
}
test();
var foo
首先会上升到函数体顶部,然而此时的foo
为undefined
,所以执行报错。而对于函数bar
, 函数本身也是一种变量,所以也存在变量上升的现象,但是它是上升了整个函数,所以bar()
才能够顺利执行。
本文参考自:
http://www.cnblogs.com/damonlan/archive/2012/07/01/2553425.html
https://segmentfault.com/a/1190000003114255
https://segmentfault.com/a/1190000005794611
作者博客:pspgbhu
作者GitHub:https://github.com/pspgbhu
欢迎转载,但请注明出处,谢谢!