概念:也称预解释;执行一个页面的时候浏览器会形成一个全局作用域,在这个作用域形成后,代码从上到下执行之前,浏览器会对带var和function关键字的进行循环查找,对带var的进行声明,对带function的进行声明加定义,这种预先处理的机制称为 变量提升;
声明:var a ,function fn 告诉浏览器有这么一个变量
定义:赋值
变量提升阶段:
带var的只声明不定义
带function声明加定义
变量提升只发生在当前作用域,在全局下声明的函数或变量是全局变量,在私有作用域下声明的函数或变量是私有变量,私有作用域形成后,也是先变量提升,形参赋值后再执行代码
举例:
1 console.log(a);//undefined
2
3 fn();//控制台输出 1
4
5 var a=0;
6
7 function fn(){
8
9 console.log(1);
10
11 }
console.log(a);//0
解释图:
暂时性死区:
在原有浏览器渲染机制先,基于typeof检测一个未被声明过的变量,不会报错,返回undefined
变量提升的特殊情况:
1、es6中的let和const不会进行变量 提升
2、es6中的块级作用域和现在的新浏览器机制:当遇到块级作用域的时候,不管条件是否成立,带var和function的都只声明不定义,进入块级作用域后才会赋值
es6中的let和const切断了全局变量和window属性的映射机制
es6中的let和const不能重复命名,虽然没有变量提升机制,但是在当前作用域代码自上而下执行之前,浏览器会做一个重复检测机制(语法检测):自上而下查找当前作用域下所有变量,一旦发现有重复的,直接抛出异常,代码也不会在执行
es6中的let和const解决了暂时性死区:在声明之前使用变量,报错is not defind
console.log(fn);//undefined console.log(a);//Uncaught ReferenceError: a is not defined
if(1==true){ let a=2;
var as=1; function fn(){ } }
console.log(window.as);//1 和window映射成
console.log(winndow.a);//undefined 没有和window映射
3、return后面的内容不会被提升,return下面的内容会变量提升
function fn(){ f();//执行,控制台输出2 return function (){ console.log(3); } function f(){ console.log(2); }
4、等号右边不会发生变量提升
console.log(fn);//undefined
var fn=function (){ }
5、自执行函数不进行变量提升,会在运行到当前定义加执行一起行进