js 变量提升,函数提升,以及为什么要变量提升??

一、变量提升

变量声明提升:

如果变量声明在函数里面,则将变量声明提升到函数的开头;

如果变量声明是一个全局变量,则将变量声明提升到全局作用域的开头;

变量提升分为两步,第一步变量声明的提升,第二步变量的赋值;

案例1:全局变量提升

console.log(a); // 'undefined'
var a = '程序员劝退师';
console.log(a); // 程序员劝退师

实际运行时代码1:

var a;      // 全局变量声明提升
console.log(a); // 'undefined'
a = '程序员劝退师';
console.log(a); // 程序员劝退师

 案例2:函数内变量提升

var a = 'global';
function fun() {
   console.log(a); // 'undefined'
   var a = 'local';
   console.log(a); // local
}
fun();

实际运行时代码2:

var a;        // 全局变量声明提升
a = 'global';    // 声明后赋值
function fun() {
   var a;      // 函数内变量声明提升
   console.log(a); // 'undefined'
   a = 'local';   // 函数内赋值
   console.log(a); // local
}
fun();

 二、函数提升

函数的提升是直接将整个函数整体提升到作用域的最开始位置,相当于直接复制到开始;

函数声明只会提升函数声明,不提升函数表达式;

函数提升后会生成一个函数表达式;

案例1:函数声明式

console.log(fun1); // [Function: fun1]
fun1(); // fun1
function fun1() {
   console.log('fun1');
}

运行时代码1:

var fun1 = function () { // 函数声明提升变为函数声明式
   console.log('fun1');
};
console.log(fun1); // [Function: fun1]
fun1(); // fun1

案例2:函数表达式,保持原来不变

console.log(fun2); // undefined
fun2(); // TypeError: fun2 is not a function
var fun2 = function () {
   console.log('fun2');
};

运行时代码2:

console.log(fun2); // undefined
fun2(); // TypeError: fun2 is not a function
var fun2 = function () {
   console.log('fun2');
};

三、提升顺序

函数声明提升比变量提升优先级要高,且不会被变量声明覆盖,但会被变量赋值时覆盖;

a() > a

案例:

console.log(a); // f a() {console.log(10)}
console.log(a()); //  undefined
var a = 3;
function a() {
   console.log(10); //10
}
console.log(a); //3
a = 6;
console.log(a()); //a is not a function;

运行时代码:

var a = function(){ // 函数声明提升
   console.log(10);
};
var a;         // 变量声明提升
console.log(a);     //  f a() {console.log(10)}
console.log(a());   //  undefined
a = 3;         // 变量赋值后进行函数覆盖
console.log(a);     // 3 
console.log(a());   // a() is not a function;

 四、变量提升的意义

我们知道在js运行时需要分两步,一步是解析阶段,一步是执行阶段;

1、容错性更好:

  js作为一个脚本语言,在代码解析阶段,对js进行预编译,就可以发现一些语法上的错误,及时抛出错误,容错性更好;

2、提高西能:

在解析阶段函数的语法检查与预编译,操作只执行一次,目的为了提升性能,

如果没有这一步,代码在每次执行时都要进行编译运行,极大的浪费性能,相对于js这种脚本语言来说;

在解析的过程中,还会为函数生成预编译代码。在预编译时,会统计声明了哪些变量、创建了哪些函数,并对函数的代码进行压缩,去除注释、不必要的空

白等。这样做的好处就是每次执行函数时都可以直接为该函数分配栈空间(不需要再解析一遍去获取代码中声明了哪些变量,创建了哪些函数),并且因为

代码压缩的原因,代码执行也更快了。

 

es6之后带来了块级作用域极大地解决了变量提升带来的问题,我们在写代码时也应该尽量避免使用重复的变量。

posted @ 2021-02-01 22:42  程序員劝退师  阅读(381)  评论(0编辑  收藏  举报