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;
}