1、什么是声明提升
JavaScript在运行时解释器存在预解释的过程。这个过程会将函数声明和变量声明提升到当前作用域顶端。声明提升只提升声明,不会提升初始化过程。
2、变量声明
- 只有使用
var
声明的变量才会发生提升。 - 使用
let
,const
创建的变量不会发生提升。 - 变量的赋值也不会发生提升。
- 没有使用
var
声明直接使用的伪全局对象,由于声明过程所以也不能提升。
num = 6;
console.log(num); // 6
var num;
//Hoisting ==>
var num; // 变量提升,初始化赋值不会提升
num = 6;
console.log(num);
3、函数声明
- 只用使用函数声明的方式声明的函数才会提升。
- 使用函数表达式的匿名函数不存在提升,因为函数名是变量形式,所以只存在变量提升。
fun();
function fun(){
console.log(1);
}
//Hoisting ==>
function fun(){ // 函数声明提升
console.log(1);
}
fun(); // 1
函数表达式的声明提升
var getName=function(){ // 函数表达式
console.log(2);
}
function getName(){
console.log(1);
}
getName();// 2
//Hoisting ==>
function getName(){ //函数声明提升到顶部
console.log(1);
}
var getName; //变量声明提升
getName = function(){ //变量赋值依然保留在原来的位置,匿名函数不会提升,只是变量提升
console.log(2);
}
getName(); // 最终输出:2 函数声明的函数被函数表达式重新赋值了
4、声明提升规则
- 声明提升只会提升到当前作用域。局部声明提升到局部作用域内,全局声明提升到全局作用域内。
num = 10;
function func () {
window.num = 5;
console.log(num);
var num;
console.log(window.num);
}
func();
//Hoisting ==>
// 首先会创建全局对象 window.num = 10,在func函数中声明num是局部变量而且没有赋值,所以第一个结果返回undefined。
// 然后在func函数中修改了window.num的值,所以第二个结果是5。
function func () { // 全局函数,会提升到window顶部
var num; // 局部变量,只会提升到了func的顶部
window.num = 5;
console.log(num);
console.log(window.num);
}
num = 10; //没有使用var创建的伪全局对象不会变量提升
func(); // undefined 5
- 函数声明提升会在变量声明提升上面。 函数声明会被变量赋值影响,但不会被变量声明影响。
var fun = 10;
console.log(typeof(fun));
function fun () {}
//Hoisting ==>
function fun () {}
var fun;
fun = 10;
console.log(typeof(fun)) // number
--------------------------------
console.log(typeof(fun));
function fun () {}
var fun = 10;
//Hoisting ==>
// 这里
function fun () {}
var fun;
console.log(typeof(fun)); // function
fun = 10;
-
对于同名的变量声明,Javascript采用的是忽略原则,后声明的会被忽略,变量声明和赋值操作可以写在一起,但是只有声明会被提升,提升后变量的值默认为undefined,结果是在赋值操作执行前变量的值必为undefined
-
对于同名的函数声明,Javascript采用的是覆盖原则,先声明的会被覆盖,因为函数在声明时会指定函数的内容,所以同一作用域下一系列同名函数声明的最终结果是调用时函数的内容和最后一次函数声明相同
-
对于同名的函数声明和变量声明,采用的是忽略原则,由于在提升时函数声明会提升到变量声明之前,变量声明一定会被忽略,所以结果是函数声明有效
如有错误,请在底部留言。