大家好,我是IT修真院成都分院第8期的學員,一枚正直純潔善良的WEB前端程序員。
今天給大家分享一下js中作用域和作用域鏈的相關(guān)問題。
一、作用域的概念
任何程序設(shè)計語言都有作用域的概念,簡單的說,作用域就是變量與函數(shù)的可訪問范圍,即作用域控制著變量與函數(shù)的可見性和生命周期。在JavaScript中,變量的作用域有全局作用域和局部作用域兩種。
全局作用域(Global Scope):
在代碼中任何地方都能訪問到的對象擁有全局作用域,一般來說一下幾種情形擁有全局作用域:
最外層函數(shù)和在最外層函數(shù)外面定義的變量擁有全局作用域,例如:
var aName="6得飛起";
function doSomething(){
var bName="步得步說";
function innerSay(){
alert(bName);
}
innerSay();
}
alert(aName);//6得飛起
alert(bName);//腳本錯誤
doSomething();//步得步說
innerSay()//腳本錯誤
所有末定義直接賦值的變量自動聲明為擁有全局作用域,例如:
function doSomething(){
bName="我愛紅色毛爺爺";
alert(bName)
}
alert(bName);//我愛紅色毛爺爺
局部作用域(Local Scope)
和全局作用域相反,局部作用域一般只在固定的代碼片段內(nèi)可訪問到,最常見的例如函數(shù)內(nèi)部,所有在一些地方也會看到有人把這種作用域成為函數(shù)作用域。
例如下列代碼中的bName和函數(shù)innerSay都只擁有局部作用域:
function doSomething(){
varbName="我今天開會";
function innerSay(){
alert(bName);
}
innerSay();
}
alert(bName);//腳本錯誤innerSay();//腳本錯誤
二、作用域鏈(Scope Chain)
有了JavaScript的作用域的劃分,那么可以將JavaScript的訪問作用域連成一個鏈式樹狀結(jié)構(gòu).
JavaScript的作用域鏈一旦能清晰的了解,那么對于JavaScript的變量與閉包就是非常清晰的了.
下面采用繪圖的辦法,繪制作用域鏈.
繪制規(guī)則:
1) 作用域鏈就是對象的數(shù)組
2) 全部script是0級鏈,每個對象占一個位置
3) 凡是看到函數(shù)延伸一個鏈出來,一級級展開
4) 訪問首先看當前函數(shù),如果沒有定義往上一級鏈檢查
5) 如此往復(fù),直到0級鏈
先看一段代碼:
var num =10;
var func1 =function(){
var num =20;
var func2 =function(){
var num =30;
alert(num);
};
func2();
};
var func2 =function(){
varnum =20;
varfunc3 =function(){
alert(num);
};
func3();
};
func1();
func2();
下面分析一下這段代碼:
-> 首先整段代碼是一個全局作用域,可以標記為0級作用域鏈,那么久有一個數(shù)組
var link_0 = [ num, func1, func2 ];// 這里用偽代碼描述
-> 在這里func1和func2都是函數(shù),因此引出兩條1級作用域鏈,分別為
var link_1 = { func1: [ num, func2 ] };// 這里用偽代碼描述
var link_1 = { func2: [ num, func3 ] };// 這里用偽代碼描述
-> 第一條1級鏈衍生出2級鏈
var link_2 = { func2: [ num ] };// 這里用偽代碼描述
-> 第二條1級鏈中沒有定義變量,是一個空鏈,就表示為
var link_2 = { func3: [ ] };
最終可以將作用域鏈表示為
// 這里用偽代碼描述varlink = [// 0級鏈num,
{ func1 : [// 第一條1級鏈num,
{ func2 : [// 2級鏈num] }
]},
{ func2 : [// 第二條1級鏈num,
{ func3 : [] }
]}
];