/ javascript

Hoisting声明提升


JavaScript程序在运行前有一个预编译的过程,而声明提升就发生在预编译的过程

预编译规则

  • 对var关键字提前声明(值先设为undefined,执行时才给实际值)


    if ("a" in window) {
    var a = 1;
    }
    console.log(a);
    //等价于
    var a;
    if("a" in window){
    a = 1;
    }
    console.log(a);

  • 对函数定义式进行提前(函数表达式不提前)

    	
      	a();		
      	function a(){
      		console.log("Hello");
      	}
    

    //等价于
    function a(){
    console.log("Hello");
    }
    a();


    //函数表达式不提前
		a();	
		var a = function (){
			console.log("Hello");
		}
    
  • 变量的解析顺序(优先级),与变量进入作用域的4种方式的顺序一致

    在JavaScript,一个变量名进入作用域的顺序:

    • Language-defined(语言内置):所有的作用域中都有 this 和
      arguments 关键字

    • Formal parameters(形式参数):函数的参数在函数作用域中都是有
      效的

    • Function declarations(函数声明):形如function foo() {}

    • Variable declarations(变量声明):形如var bar;

	
	function testOrder(arg) {
		console.log(arg); // arg是形参,不会被重新定义
		console.log(a); // 因为函数声明比变量声明优先级高,所以这里a是函数
		var arg = 'hello'; // var arg;变量声明被忽略, arg = 'hello'被执行
		var a = 10; // var a;被忽视; a = 10被执行,a变成number
		var b = 20;
	    function a() {
	        console.log('fun');
	    } // 被提升到作用域顶部
	    console.log(a); // 输出10
	    console.log(arg); // 输出hello
		console.log(b);
	}; 
	testOrder('hi');
    

等价于:

	
	 function testOrder(arg) {
  		// Language-defined  this && arguments
  		// 形参				 arg
  		//函数声明
	    function a() {
	        console.log('fun');
	    } 
	    //变量声明
	    var b;


		console.log(arg); // arg是形参,不会被重新定义
		console.log(a); // 因为函数声明比变量声明优先级高,所以这里a是函数
		arg = 'hello'; // var arg;变量声明被忽略, arg = 'hello'被执行
		a = 10; // var a;被忽视; a = 10被执行,a变成number
		b = 20;
	    console.log(a); // 输出10
	    console.log(arg); // 输出hello
	    console.log(b);
	}; 
	testOrder('hi');
    

ES2015

* ES5只有两种声明变量的方法:var 和 function。
* ES6添加了let,const,class 和 import。所以,ES6一共有6种声明变量的方法。(let,const,class不存在变量提升)