js函数预解析
  1. 例子1:
  • 先上一段代码,看看能不能写出最终的执行结果.
    console.log(a);
    var a = 1;
    console.log(a);
    function a(){
        console.log(2);
    }
    var a = 3;
    console.log(a);
    function a(){
        console.log(4);
    }
    console.log(a);
    a();
  • 运行结果:

  • 解释一下:

    • 首先预解析阶段遇到 var a = 1;声明变量a
    • 然后遇到第一个函数a声明,这时由于和变量a重名,故将变量a替代,此时a表示一个函数
    • 然后遇到var a = 3;变量a干不过函数a,a代表的还是一个函数
    • 最后又遇到第二个函数a声明,后面函数a声明替换前面的,a还是代表一个函数但是函数体内容发生了变化
  • 注意: 预解析阶段的变量可以理解为都被赋值为undefined,函数就是函数体的内容,当遇到变量名a和函数名a一致时,预解析完后a是函数a,里面存放的是函数体的内容,函数a和函数a同时出现时,后面声明的函数还会覆盖前面声明的函数。

故:

    console.log(a); //输出函数a,函数体内容是第二个函数声明
    var a = 1; //经过赋值之后,函数a变为了变量a,并且值为1
    console.log(a);//1
    function a(){
        console.log(2);
    }
    var a = 3;//变量a变为3
    console.log(a);//3
    function a(){
        console.log(4);
    }
    console.log(a);//3
    a();//a现在是一个变量,当然会报错
  1. 例子2
var a =1;
function fn(a){
	console.log(a)
	a = 2;
}
fn():
console.log(a);
  • 运行结果:

  • 主要想说明的一点就是function fn(a) 就相当于function fn(var a),因此预解析阶段是有对这个函数内部的a的预解析的,因此在函数内部输出的a为undefined而没有报错。

  • 将上面的例子稍微改动一下

    var a =1;
    function fn(a){
    console.log(a)
    a = 2;
    }
    fn(a): //将a的值传递进去
    console.log(a);
    
  • 运行结果:

  • 将a当作实参传递进去之后,局部变量a的值变为1,再函数内部将a变为2,但是在外部输出时输出的是全局作用域下的a,因此还是1.

  • 注意在函数内部a=2;当没有变量a的声明时,那么a=2生成的是全局作用域下的a,但是当函数内部有局部作用域下的a时,a=2仅仅就是赋值的作用。