js特点:
单线程
解释性语言:翻译一句执行一句
js运行三部曲
1.语法分析
通篇扫描一遍,但是不执行
2.预编译
3.解释执行
预编译
函数声明 整体提升
变量 声明提升
预编译前奏
-
暗示全局变量 imply global
即任何变量,如果变量未经声明就赋值,此变量为全局对象 window所有。全局对象是window。
function fn(){var a=b=123;}
123赋值给b,此时b未声明,归window所有,window.b=123;
声明a,再把b赋值给a,window.a=undefined -
全局上的任何变量,即使声明了,也归全局所有。也就是说 一切声明的全局变量,全是window的属性。
window 就是全局的域。
预编译过程
预编译发生在函数执行的前一刻
- 创建AO对象 Activation Object (执行期上下文)
- 在函数里面找形参和变量声明,将变量和形参的名作为AO属性名,值为undefined
- 将实参和形参相统一
- 在函数体里面找函数声明,将函数名作为AO属性名,值为函数体
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);
找形参和变量声明,形参是a,变量声明是 a,b;a重复了 不用写;
AO{
a:undefined,
b:undefined,
}
将实参和形参相统一
AO{
a:1,
b:undefined,
}
在函数体里面找函数声明
AO{
a:function a() {},
b:undefined,
d:function d() {}
}
函数执行按顺序来,预编译时声明提升过不用再看了,
function a() {}
123
123
function () {}
全局
- 创建GO对象 Global Object,GO===window
- 找变量声明,将变量的名作为GO属性名,值是undefined
- 将函数声明 的函数名作为GO的属性名,值是函数体
console.log(test);
function test(test){
console.log(test); //function test() {}
var test=234;
console.log(test); //234
function test(){}
}
test(1);
var test=123;
生成GO,变量声明
GO{
test:undefined,
}
函数声明
GO{
test:function test(test){
console.log(test);
var test=234;
console.log(test);
function test(){}
}
}
执行test(1)之前,生成AO对象,找形参和变量声明
AO{
test:undefined,
}
形参实参相统一
AO{
test:1,
}
找函数声明
AO{
test:function test() {}
}
案例
function test(){
console.log(b); // undefined
if(a){ //a此时是undefined 不执行if语句
var b = 100;
}
console.log(b); // undefined
c = 234;
console.log(c); //234
}
var a;
test();
a = 10;
console.log(c); // 234
先生成GO
GO{
a:undefined,
test:
}
执行test之前,生成AO对象
GO{
a:undefined,
test:,
c:undefine,
}
AO{
b:undefined,
}
执行c=234
GO{
a:undefined,
test:,
c:234,
}
AO{
b:undefined,
}
执行a=10
GO{
a:10,
test:,
c:234,
}
AO{
b:undefined,
}