javascript之预编译
javascript -- 预编译
js特点:
解释性语言 单线程js执行过程
-语法分析
语法分析就是javascript在执行文档之前会进行一个语法的分析,通俗的意思就是先大概扫描一遍,看看有没有犯最低级的语法错误,如果有,那就报错。
错误正常分两种:
- 语法错误(低级错误)
- 逻辑错误(正常错误)
- 预编译
函数声明,整体提升 变量,声明提升//函数 test(); function test(){ console.log(a); } //这样的函数能正确执行,原因是因为函数整体提升了,函数永远在逻辑的最前面,所以无论你在哪里执行,无所谓
//变量 console.log(a); var a = 123; //这样的变量不能正确执行,会提示undefined,因为变量提升了,但是变量提升的时候,值并不会跟着提升。如下: var a; console.log(a); a = 123;
预编译前奏
列表内容inply global 暗示全局变量 : 即任何变量未经声明就赋值,此变量就为全局变量(window)所有.// 例如 a = 123;//这个就是全局变量所有的 var a = b = 123;//解释如下 //自右向左执行 var a = b b = 123; //这样子做有个缺陷,会产生一种结果,a是声明的变量,而b是window的未声明的变量 var a = b = 123; var a. b = 123, a = b //在function里面执行的结果 fucntion test(){ var a = b =123; } console.log(window.a);//undefined console.log(window.b);//123; //原因是,a属于test的域里面,而且声明了,不归window所有,而b是没有声明的变量,所以是window所有
一切声明的全局变量,都是window的属性
var a = 123 ===> window.a = 123;
window是什么呢?
window就是一个仓库,就是一个全局的域,window也是一个对象
window就是全局
var a = 123; var b = 456; var c = 789; //因为所有的声明的全局变量都是window的属性,所以可以理解为: window{ a:123; b:456; c:789; } //因为window是对象!对象!对象! console.log(a) ==> console.log(window.a) //相等
只要是全局的,全都是window的
预编译四部曲
题目:
<script> function fn(a) { console.log(a); var a = 123; console.log(a); function a() {} console.log(a); var b = function () {} console.log(b); function d() {} } fn(1); </script>
- 创建ao对象(activation object)
ao{ }
- 找形参和变量声明,将变量和形参名作为ao属性名,值为 undefined
ao{ a:undefined, b:undefined, }
- 将实参值和形参值统一
ao{ a:1, b:undefined, }
- 在函数体里面找函数声明,值赋予函数体
ao{ a:function a (){}, b:undefined, d:function d (){}, }
最后进行执行
首先一句一句执行,执行第一句console.log(a);那么,会在ao对象中调取a,
在ao对象中a等于function a(){},那么就输出function a(){},然后到达第二句,
var a = 123,var a 已经被提升了,所以不用管,直接到a = 123,所以,在
ao对象中,a变成了123
ao{ a:123, b:undefined, d:function d (){}, }
ao对象变成123后,再来进行执行第三句,console.log(a);那么,现在a等于123,那么就是输出123,
到达第四句,第四句是函数,由于函数已经被提升了,所以没有这一步,然后再到第五句,第五句是console.(a),所以输出还是123吧,然后再到第六句,第六句是var b = function (){},所以就要把在ao对象中的b的属性改为function(){}
``` ao{ a:123, b:function(){}, d:function d (){}, }
所以在第七句b的输出就是function(){},第八句直接被提升了,所以不用读了。总提答案为:
function a(){} 123 123 function(){}
注意点:预编译发生在函数执行的前一刻
预编译练习题
<script> function test(a,b) { console.log(a); c = 0; var c ; a = 3; b = 2; console.log(b); function b() {} function d() {} console.log(b); } test(1); </script>
答案解释
//1.创建ao对象 ao { } //2.找形参和变量声明,将变量和形参名作为ao属性名,值为 undefined ao{ a:undefined, //形参声明 b:undefined, //形参声明 c:undefined, //变量声明 } //3.将实参值和形参值统一 ao{ a:1, //因为a的实参为1,所以为1 b:2, //因为b的值为2 c:0, //因为c的值为0 } //4.在函数体里面找函数声明,值赋予函数体 ao{ a:1, //因为a的实参为1,所以为1 b:function d(){} , //因为b有函数体 c:0, //因为c的值为0 d:function d(){} //因为d有函数体 } 最后进行执行,从第一句读下来,答案如下: 1. a == 1 2. c == 0 3. var c 因为提升了,所以不用读 4. a == 3 5. b == 2 6. b == 2 7.因为提升了,所以不用读 8.因为提升了,所以不用读 9. b == 2 最后答案为 1 2 2
预编译练习题2
<script> function test(a,b) { console.log(a); //只要有函数表达式,那么肯定是函数表达式 function(){} console.log(b); //undefined var b = 234; console.log(b); //234 a = 123; console.log(a); //123 function a (){} //函数声明 var a; b = 234; var b = function () {}; //函数表达式 console.log(a); //123 console.log(b); //function(){} } test(1); </script>
预编译分两个,第一个是全局的预编译,第二个是函数的预编译
全局的预编译如下:
创建go对象(global object) go也就是window 找形参和变量声明,将变量和形参名作为ao属性名,值为 undefined 在函数体里面找函数声明,值赋予函数体函数的预编译如下:
创建ao对象 找形参和变量声明,将变量和形参名作为ao属性名,值为 undefined 将实参值和形参值统一 在函数体里面找函数声明,值赋予函数体注意点:如果没有声明的变量,会放到go去预编译的。
function test(){ var a = b = 123; console.log(window.a) //undefined console.log(window.b) //123 } /* ao{ a : 123; } go{ b : 123; } */
全局加函数预编译练习题
<script> function test() { console.log(b); //undefined if (a) { var b = 100; } c = 234; console.log(c); //234 } var a; test(); a = 10; console.log(c); //234 /* go{ test:undefined, c:234, a:undefined } ao{ b = undefined }*/ </script>
baidu 2013 面试题
//1. function bar() { return foo; foo = 10; function foo() { } var foo = 11; } console.log(bar());
//2. console.log(bar()); function bar() { foo = 10; function foo() { } var foo = 11; return foo; }
- 解释执行
推荐阅读