变量提升机制

278 阅读3分钟

虽然说随着ES6/ES7等一些新语法的出现,变量提升变得不再那么重要,但是现在的代码还是会出现类似于var等的语句,多了解一些他们的底层机制,对我们写代码不可获取.

语法

变量提升:在当前上下文中(全局/私有/块级),JS代码自上而下执行之前,浏览器会提前处理一些事情(可以理解为词法解析的一个环节,词法解析一定发生在代码执行之前) 会把当前上下文中所有带VAR/FUNCTION关键字的进行提前的声明或者定义

var a=10;
声明(declare):var a;
定义(defined):a=10;
带VAR的只会提前的声明
带FUNCTION会提前的声明定义


1.代码执行之前:全局上下文中的变量提升
     var a;   默认值是undefined
// console.log(a); //=>undefined
// var a = 12; //=>创建值12  不需要在声明a了(变量提升阶段完成了,完成的事情不会重新处理) a=12赋值
// a = 13; //全局变量a=13
// console.log(a); //=>13

2.全局上下文中的function变量提升
 func=函数   函数在这个阶段赋值都做了
 func();
function func() {
	var a = 12;
	console.log('OK');
} 

注意:var声明的函数表达式只会存在变量提前声明,不会赋值

 func(); //=>Uncaught TypeError: func is not a function
  var func = function () {
  真实项目中建议用函数表达式创建函数,因为这样在变量提升阶段只会声明FUNC,不会赋值
 	console.log('OK');
 };
 func();

函数具名化意义

1.// var func = function AAA() {
// 	// 把原本作为值的函数表达式匿名函数“具名化”(虽说是起了名字,但是这个名字不能在外面访问 =>也就是不会在当前当下文中创建这个名字)
// 	// 当函数执行,在形成的私有上下文中,会把这个具名化的名字做为私有上下文中的变量(值就是这个函数)来进行处理
// 	console.log('OK');
// 	// console.log(AAA); //=>当前函数
// 	// AAA(); 递归调用   而不用严格模式下都不支持的 arguments.callee 了
// };
// // AAA();  //=>Uncaught ReferenceError: AAA is not defined
// func();


2.EC(G)变量提升 (未定义)
 */
// console.log(a); //=>Uncaught ReferenceError: a is not defined
// a = 13;
// console.log(a);



 3.EC(G)变量提升   只有VAR/FUNCTION会变量提升(ES6中的LET和CONST不会) 
 
/* console.log('OK'); //=>'OK'
console.log(a); //=>Uncaught ReferenceError: Cannot access 'a' before initialization  不能在LET声明之前使用变量
let a = 12;
a = 13;
console.log(a); */

变量映射机制

基于“VAR或者FUNCTION”在“全局上下文”中声明的变量(全局变量)会“映射”到GO(全局对象window)上一份,作为他的属性;而且接下来是一个修改,另外一个也会跟着修改;
 */
// var a = 12;
// console.log(a); //=>12  全局变量
// console.log(window.a); //=>12 映射到GO上的属性a

// window.a = 13;
// console.log(a); //=>13 映射机制是一个修改另外一个也会修改

新旧浏览器对于条件语句函数提升机制

EC(G):全局上下文中的变量提升
 *    不论条件是否成立,都要进行变量提升(细节点:条件中带FUNCTION的在新版本浏览器中只会提前声明,不会在提前的赋值了)
 *   [老版本]
 *      var a;
 *      func=函数;
 *   [新版本]
 *      var a;   全局上下文中声明一个a也相当于 window.a
 *      func;

注意:为了兼容ES6语法,存在块级作用域。大括号中出现Let/const/function都会被认为是块级作用域