console.log( a );
var a = 2;
执行输出undefined
a = 2;
var a;
console.log( a );
执行输出2
说明:javaScript
运行时在编译器阶段会最先处理var a;
也就是变量被提升
foo();
function foo() {
console.log( a ); // undefined var a = 2;
var a = 2;
}
执行输出undefined
,执行foo();
时找到了函数的声明,但实际代码写在foo()
的后面。说明函数声明会被提升,函数作用域里变量也会被提升
foo();
var foo = function bar() {
console.log(a)
var a =2
};
执行输出TypeError: foo is not a function,说明函数表达式不会被提升,
foo()
由于对 undefined
进行调用抛出TypeError
异常
var foo;
foo(); // 1
foo = function() {
console.log( 2 );
};
function foo() {
console.log( 1 );
}
执行输出1,说明虽然函数和变量都能被提升,但是函数声明提升优先于变量声明提升
foo(); // 3
function foo() {
console.log( 1 );
}
var foo = function() {
console.log( 2 );
};
function foo() {
console.log( 3 );
}
执行输出3
,后面的函数声明会覆盖前面的函数声明
总结
var 变量声明和函数声明其实跟javaScript
运行原理有关,在javaScript
运行之前会先进行编译,在编译阶段会先为变量和函数根据作用域规则开辟内存空间并初始化变量为undefined
,而函数是初始化函数变量并且直接赋值函数体,以便在执行的时候方便查找和存储。
let , const到底有没有有变量提升?
console.log(a)
let a=2
输出:ReferenceError: Cannot access 'a' before initialization
,表明变量没有被定义,不能在变量为初始化之前使用。其实从这句话看来js
是找到了变量a
的,但a
还没有被初始化;这样看来,let
其实也有变量提升(在我理解上来说,提升就是先为变量创造内存空间),js
处理let
声明变量的过程:
{
let x = 1
x = 2
}
1、查找let
声明的变量x
,并在作用域中创建变量,不进行初始化
2、执行代码x=1
,初始化为1
3、执行x = 2
赋值为2
let 特性
let a=2
let a=3
console.log(a)
输出:SyntaxError: Identifier 'a' has already been declared
,不能重复定义变量
参考资料
《你不知道的javaScript 上卷》第四章 变量提升