预编译
js 执行
1.语法分析:检查代码以及语法是否有错,如果报错则不执行后面的代码
2.预编译:在内存中开辟一段空间,存储变量和函数
3.解释执行:执行代码
预编译的步骤
1.创建AO(Activation Object)
2.找到函数的形参和变量声明,将变量和形参作为AO的属性名,复赋值undefined
3.将形参和实参统一,将实参的值给形参
4.寻找函数中的函数声明,将函数名作为AO的属性名,值为函数体
函数的声明是(function fun(){} 不是var fun = function{})
函数作用域
例如:function fun(a, b) {
console.log(a)
console.log(b)
var a = 20;
var b = 30;
console.log(b)
console.log(a)
function a() {}
var a = function() {}
var b = function() {}
a = 50
// function b() {}
console.log(a)
console.log(b)
}
fun(10)
创建AO并且赋值undefined
AO:{
a : undefined
b : undefined
}
将实参赋值给形参
AO:{
a:10
b : undeined
}
寻找函数中函数声明
AO :{
a : function a(){}
b : undeined
}
代码执行
function fun(a, b) {
console.log(a) //AO对象的值为 function a(){}
console.log(b) //undefined
var a = 20;
var b = 30;
console.log(b) // 30
console.log(a) // 20
function a() {} 不执行
var a = function() {}
var b = function() {}
a = 50
console.log(a) // 50
console.log(b) 30
}
fun(10)
全局作用域 1.创建GO对象
GO{
}
2.找到全局中的变量声明,将函数和形参名的作为GO对象的属性名,值为undefined
GO{
fun :undefined
}
3.找到全局中函数声明将函数作为GO对象的属性名,值为函数
GO{
fun :function fun(){}
}
代码执行结果为function a(){}
作用域链
var num = 10
function f1(){
var num = 20
function f2(){
var num = 30
function f3(){
var num = 40
console.log(num)
}
f3()
}f2()
}
f1()
这个函数执行结果为 40
如果没有 var num = 40 ; 结果为 30
如果没有 var num = 30 ; 结果为 20
如果没有 var num = 20 ; 结果为 10
如果没有 var num = 10 ; 结果是报错
函数在调用参数时会从函数内部到函数外部逐个”搜索“参数,一直找到参数为止,如果没有声明就返回null,声明了没有赋值就返回undefined,就像沿着一条链子一样去搜索,这就是作用域的链式调用。