在JavaScript中, 提升是在代码执行之前将所有声明移到作用域顶部的默认行为。基本上, 它给我们带来的好处是, 无论在何处声明函数和变量, 无论它们的作用域是全局的还是局部的, 它们都将移至其作用域的顶部。
它使我们能够在甚至将其写入代码之前调用函数。
注意:JavaScript仅提升声明, 而不提升初始化。
让我们了解这到底是什么:
以下是变量声明和初始化的顺序。
声明–>初始化/赋值–>使用
// Variable lifecycle
let a; // Declaration
a = 100; // Assignment
console.log(a); // Usage
但是, 由于JavaScript允许我们同时声明和初始化变量, 所以这是最常用的模式:
let a = 100;
注意:永远记住, JavaScript在后台首先声明变量, 然后对其进行初始化。最好在执行任何代码之前先处理变量声明。
但是, 在javascript中, 未声明的变量在执行分配它们的代码之前不存在。因此, 在执行赋值时, 将值分配给未声明的变量会隐式将其创建为全局变量。这意味着所有未声明的变量都是全局变量。
// hoisting
function codeHoist(){
a = 10;
let b = 50;
}
codeHoist();
console.log(a); // 10
console.log(b); // ReferenceError : b is not defined
输出如下:
说明:在上面的代码示例中, 我们创建了一个名为codeHoist()的函数, 其中有一个未使用let / var / const声明的变量和一个let变量b。未声明的变量由javascript分配了全局作用域, 因此我们可以在函数外部打印它, 但是在变量b的情况下, 作用域是受限的, 并且在外部不可用, 并且我们得到ReferenceError。
注意:ReferenceError和未定义错误之间有区别。当我们有一个未定义或明确定义为未定义类型的变量时, 将发生未定义错误。尝试访问以前未声明的变量时, 抛出ReferenceError。
ES5
当我们谈论ES5时, 我们想到的变量是var。与let / const相比, 使用var进行提升有些不同。让我们利用var来看看提升的工作原理:
// var code (global)
console.log(name); // undefined
var name = 'Mukul Latiyan' ;
输出如下:
说明:
在上面的代码中, 我们尝试控制台变量名, 该变量名稍后声明并分配, 然后使用它, 编译器给我们
未定义
我们没有想到, 因为我们应该得到
ReferenceError
因为我们甚至在声明名称之前都在尝试使用名称变量。
但是解释器对此有不同的看法, 上面的代码如下所示:
//how interpreter sees the above code
var name;
console.log(name); // undefined
name = 'Mukul Latiyan' ;
输出如下:
函数范围变量
让我们看看如何提升函数范围变量。
//function scoped
function fun(){
console.log(name);
var name = 'Mukul Latiyan' ;
}
fun(); // undefined
输出如下:
与在全局声明变量的代码相比, 这里没有什么区别, 因为解释器看到的代码是:
//function scoped
function fun(){
var name;
console.log(name);
name = 'Mukul Latiyan' ;
}
fun(); // undefined
输出如下:
为了避免这种陷阱, 我们可以确保
在使用之前, 同时声明和分配变量
。像这样:
//in order to avoid it
function fun(){
var name = 'Mukul Latiyan' ;
console.log(name); // Mukul Latiyan
}
fun();
输出如下:
ES6
让
我们知道, 用let关键字声明的变量是块作用域作用域, 而不是函数作用域作用域, 因此, 在起吊方面没有任何问题。
例子:
//let example(global)
console.log(name);
let name= 'Mukul Latiyan' ; // ReferencError: name is not defined
输出如下:
像以前一样, 对于var关键字, 我们希望日志的输出未定义。但是, 由于es6 let不会使用未声明的变量来帮助我们, 因此解释器会明确吐出Reference错误。这样可以确保我们始终
宣布
我们的变量优先。
const
举升时的行为与let相似。