函數內部一層一層往上找最後找到全局window ,造成的鏈條就叫作做用域鏈。函數
經典例題一對象
function t(age){
var age = 5;
console.log(age);
}
t(99);//5;作用域
分析io
一共四步:console
1 任何參數執行建立AO(Active Object)對象 function
t.AO = {}變量
2 將函數的參數做爲AO的屬性寫入 co
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)}