Javascript 学习笔记(一)

  最近在学习ES6的时候,看到ES6相对于ES5新增了块级作用域,在ES5中内层变量可能会覆盖外层变量,引起全局变量的污染

var tmp = new Date();

function f() {
  console.log(tmp);
  if (false) {
    var tmp = "hello world";
  }
}

f(); // undefined

  刚开始不知道为什么输出的是undefined,后来才想起了JavaScript执行之前会有一个词法分析的过程。上面代码中,函数f执行后,输出结果为undefined,,原因在于变量提升,导致内层的tmp变量覆盖了外层的tmp变量。所以这里,将之前学的有JavaScript词法分析的知识整理一遍,方便已有记忆。

  JavaScript代码自上而下执行,引擎负责整个代码的编译以及运行,编译器则负责词法分析、语法分析、代码生成等工作而作用于则如我们熟知的一样,负责维护所有的标识符(变量),但是在js代码执行前,会首先进行词法分析,所以事实上,js运行要分为词法分析执行两个阶段。

词法分析:

  词法分析主要分为3步

    第1步:分析形参
    第2步:分析变量声明
    第3步:分析函数声明

  如果存在函数嵌套,则从外往内进行词法分析

代码演示与分析: #1

function fn1(age,hei) {
  alert(age); // 32 var age = 12; //进行赋值 AO[fn1].age=12 alert(age); // 12 alert(hei); // undefined } fn1(32);

  词法分析:    

    在函数 fn1 调用的瞬间,会产生一个AO(Active Object)对象:    

    1.分析形参

      ① 分析函数的形参,然后将形参作为AO的属性,并且属性的值是 AO.age=undefined、AO.hei=undefined;
      ② 分析函数的实参列表,会把形参列表和函数内部的一个arguments对象(保存当前函数的实参列表,类似数组)形成一个一一对应的关系:arguments[0]=32;分析完实参之后,会检查arguments对象和AO对象的关系——AO.age=arguments[0]=32,AO.hei依然是undefined;    

    2.分析 var 声明的变量

      分析函数内部 var 声明的变量,去检查AO对象上是否存在同名的属性,如果存在,则不作任何的处理;如果不存在则将变量作为AO对象的属性,并且属性的值为undedined即: AO.age=undefined;

    3.分析 function 声明的函数

       没有

  执行过程:

    alert( age )   // 32

    alert( age )  //12  代码执行在这之前的  var age=12 会重新给 AO对象的 age属性赋上新的值

    alert( hei )  //undefined

代码演示与分析: #2 

function a(b) {
	alert(b);
	function b(){
		alert(b);
	}
	b();
}
a(1);

  词法分析:

    在函数 a 调用的瞬间,会产生一个AO(Active Object)对象:AO[a]

    1.分析形参

      ① 分析函数的形参b,然后将形参作为AO[a]的属性,并且属性的值是 AO[a].b=undefined;

      ②分析传参,将实参列表与作用域链内部的arguments对象进行对比,arguments[0]=1AO[a].b=arguments[0]=1

    2.分析 var 声明的变量

      没有

    3.分析 function 声明的函数

      分析函数内部的 function 声明的函数, 如果在AO[a]上发现了与函数名相同的属性,则直接覆盖;如果没有则将其设置成AO[a]的属性,属性的值就是这个函数的表达式:AO[a].b= function b(){ alert(b) }

  执行过程:

    alert(b);   // function b(){ alert(b) }

    b();         //执行的过程中,会在自身的 AO[b]上查找属性,如果自身不存在则会去外层的 AO上查找,如果外层还是不存在则会去全局的window上面查找,AO查找的这条连就是作用域链,所以->function b(){ alert(b) }

    

 代码演示与分析: #3

function test(a) {
	console.log(a);
	console.log(b);
	var a = 10;
	var b = 11;
	console.log(a);
	console.log(b);

	var a = function () {
		var d =10;
	}

	function e() {
		var f = 10;
	}

	console.log(a());
	console.log(a);
	console.log(a);

}
test(1)

  词法分析:

    1.分析形参

      AO[test].a = undefined  —>    arguments[0] = 1   —>   AO[test].a = arguments[0] = 1

    2.分析 var 声明的变量

      AO[test].a = 1 (已存在属性,不做操作)    AO[test].b = undefined 

    3.分析 function 声明的函数

      AO[test].e = function e() { var f = 10; }

   执行过程:

    console.log(a);   // 1

    console.log(b);  // undefined

    console.log(a);   // 赋值AO[test].a = 10  —>   10

    console.log(b);  // 赋值AO[test].b = 11  —>   11

    console.log(a());  //a方法,没有返回值。默认返回 undefined

    e();                      //e方法,没有返回值。默认返回 undefined

    console.log(a);   // AO[test].a = function { var d =10;}   当代码执行到第二个var a时,javascript引擎由于第一步编译器忽略了重复声明的var,且作用域中已经有a,所以重复声明会发生值的覆盖,但并不会报错

原文地址:https://www.cnblogs.com/jinxiblog/p/7494717.html