函数内部一层一层往上找最后找到全局window ,形成的链条就叫做作用域链。
经典例题一
function t(age){
var age = 5;
console.log(age);
}
t(99);//5;
分析
一共四步:
1 任何参数执行创建AO(Active Object)对象
t.AO = {}
2 将函数的参数作为AO的属性写入
t.AO = {age:99}
3 分析函数内部var
因为AO对象内部已经有了age所以舍弃内部var的声明,注意:舍去的只是声明,不舍去赋值
4 分析函数内部函数,如果有函数,则函数覆盖参数变量
没有内部函数
分析完毕此时t.AO = {age:99}
------------------------以上只是分析而已以下是执行-----------------------------
开始执行:
age = 5;
所以t.AO.age = 5;
所以t(99)答案为5;
经典例题2:
若函数里边有函数且函数名于参数名字相同,则函数会覆盖参数
function t(greet){
console.log(greet);
function greet(){
alert("hello");
}
}
t(3);
1参数 t.AO = {greet:3}
2 函数内var 没有
3 函数内函数 有
t.AO = {
greet:function (){
alert("hello");
}
}
经典例题3
function t(arg){
(1)console.log(arg);//3
(2)var arg= function (){//只是一个函数表达式
alert("hello");
}
(3)console.log(arg);//function (){alert("hello")}
}
t(3);
分析:
1 创建对象 : t.AO = {}
2 参数: t.AO = {arg : 3}
3 函数内var,有。但是与参数同名忽略声明,注意不忽略执行
此时 t.AO = {arg : 3}
4 函数内函数 ,没有,此时 t.AO = {arg : 3}
开始执行从上到下:
(1)执行结果为 t.AO = {arg : 3} 所以值为3
(2)执行赋值语句arg = function(){alert("hello")}
(3)执行赋值语句t.AO = {arg : function(){alert("hello")}}
注意:函数表达式优先级低于函数声明
function a(b){
(1)console.log(b);
function b(){
console.log(b);
}
b();
}
a(1);
1 a.AO = {}
2 a.AO = {b:1}
3 var 没有
4 function 覆盖
a.AO = {
b:function(){
console.log(b);
}
}
a 函数分析完成 开始执行 (1)
b 结果为function
分析内层b函数
1 b.AO = {}
2 没有
3 没有
4 没有
结果为 b.AO = {}
开始执行:b.AO 里面没有属性顺着作用域往上找 a.AO 里面的属性
找到了b:function
例题5
function a(b) {
(1)alert(b);
(2)var b = function() {
(3)alert(b);
}
b();
}
a(1);
1 a.AO = {};
2 a.AO = {b:1};
3 略去声明,不舍去赋值 a.AO = {b:1};
4 没有
执行a :
(1) = 1;
(2) 赋值 a.AO = {b:function(){alert(b)}};
// 函数在调用时候分析
分析b:
b.AO = {},b里面没有找a的
执行b:
(3) = b:function(){alert(b)}