今天没事情回顾了一下我在在去年4-6月份学习JavaScript程序设计的笔记。发现书到用时方恨少,简单的太简单,难的不用的看来一会才慢慢看懂。
1.预编译
预编译主要用来解决所有的JavaScrip代码执行顺序的问题。javascript相对于其它语言来说是一种弱类型的语言,在其它如java语言中,程序的执行需要有编译的阶段,而在javascript中也有类似的“预编译阶段”,了解javascript引擎的执行机理,将有助于在写js代码过程中的思路总结。
举个例子来讲解一下(举得例子比较难,不太好懂,但能很好的讲解出预编译的过程):
function test(a){ //在这里a是形参 console.log(a); var a = '123'; //a在被声明并且赋值 console.log(a); function a(){}; //a在这里被函数声明 console.log(a); var b = function (){ return '函数b'; }(); console.log(b); } test(1);
这个例子非常的恶心,他的形参,变量名,函数名用的都是 a,就出现了覆盖执行的问题,下面我们来解决这个问题。
如果是顺序执行会依次打印:1 ,123,function a(){},函数b。实际结果输出的是:function a(){},123,123,函数b。
之所以会这样,是因为在预编译的时候执行前上下文规定了它执行的顺序。
预编译主要分为四部:
(1)创立AO对象。在函数上下文中,我们用活动对象AO(activation object)来表示变量对象。
(2)找到形参和声明变量,将变量名和形参名作为AO的属性名。值暂时为undefined。
(3)将实参和形参统一。
(4)在函数体里面找到函数声明,值赋予函数体。
第一步:AO对象建立,AO{ };
第二步:a作为形参出现一次,作为声明变量出现一次。b作为声明变量出现一次。同一个值声明或者作为形参多次我们只写一个。所以现在AO就是:
AO{
a:undefined,
b:undefined
}
第三步:将实参和形参统一。实参就是test(1)里面的1,形参是test(a)里面的a,所以现在AO就是:
AO{
a:1,
b:undefined
}
第四步:在函数体里面找到函数声明,值赋予函数体。函数体只有a(),所以将函数赋值给a,所以现在AO就是:
AO{
a:function a(){},
b:undefined
}
预编译结束,根据AO和页面代码开始执行,所以:
开始执行代码的时候,AO是:
AO{
a:function a(){},
b:undefined
}
所以第一次打印是:function a(){};
代码继续执行到var a = '123';
由于预编译已经声明,所以这一行只执行赋值语句 a='123';
所以第二次打印是:123
代码继续执行到function a(){};函数声明已经在预编译执行完毕,不执行
所以第三次打印还是:123
代码继续执行到var b = function (){ return '函数b';}();
预编译已经声明,所以这一行只执行赋值语句 b = function (){ return '函数b';}();
所以第四次打印的是b,b是一个立即执行函数,返回值就是:函数b
结论:预编译能解决所有的代码执行顺序的问题。即使不明白JavaScript的预编译也不太影响,日常对JavaScript的操作,但明白以后会对我们的理解会有很大的帮助。
2.闭包
内部数据保存到外部导致闭包。
3.面向对象的程序设计