用一句话来描述 javascript 中的托管是将变量和函数提升到声明它们的范围的顶部。
我假设您是初学者,首先要正确理解提升,我们已经了解 undefined 和 ReferenceError
之间的区别
var v;
console.log(v);
console.log(abc);
/*
The output of the above codes are:
undefined
ReferenceError: abc is not defined*/
现在在下面的代码中我们看到了什么?变量和函数表达式被清除。
<script>
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
</script>
但真实的图片证明变量和函数都被提升到了作用域的顶部:
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));
前两个日志的输出是 undefined 和 TypeError: getSum is not a function 因为 var totalAmo 和 getSum 像下面这样被吊在其范围的顶部
<script>
var totalAmo;
var getSum;
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
console.log(totalAmo);
console.log(getSum(9,7));
</script>
但对于函数声明,整个函数都被提升到其作用域的顶部。
console.log(getId());
function getId(){
return 739373;
}
/* output: 739373, because the whole function hoisted on the top of the scope.*/
现在同样的逻辑也适用于在函数范围内声明的变量、函数表达式和函数声明。 关键点:它们不会被吊到文件顶部;
function functionScope(){
var totalAmo;
var getSum;
console.log(totalAmo);
console.log(getSum(8,9));
var totalAmo = 8;
var getSum = function(a, b){
return a+b;
}
}
因此,当您使用 var 关键字时,变量和函数会在作用域(全局作用域和函数作用域)的顶部提升。
let 和 const 呢,const 和 let 仍然像 var 一样知道全局作用域和函数作用域,但是 const 和 let 变量也知道另一个作用域称为阻塞范围。只要有代码块,就存在块作用域,例如 for 循环、if else 语句、while 循环等。
当我们使用 const 和 let 在这些块范围内声明一个变量时,变量声明只会被提升到它所在的块的顶部,而不会被提升到父函数的顶部或它被提升的全局范围的顶部。
function getTotal(){
let total=0;
for(var i = 0; i<10; i++){
let valueToAdd = i;
var multiplier = 2;
total += valueToAdd*multiplier;
}
return total;
}
上面例子中的变量会像下面这样被提升
function getTotal(){
let total;
var multiplier;
total = 0;
for(var i = 0; i<10; i++){
let valueToAdd;
valueToAdd = i;
multiplier = 2;
total += valueToAdd*multiplier;
}
return total;
}