JavaScript作用域
簡單的說侵贵,作用域就是變量與函數(shù)的可訪問范圍癞蚕,即作用域控制著變量與函數(shù)的可見性和生命周期蝇率。在JavaScript中,變量的作用域有全局作用域和局部作用域兩種狭园。
<script type="text/javascript">
var v = 20; //定義了一個全局變量,那么這個變量在當(dāng)前的JS腳本部分都可以
function(){
var v = 10糊治;//在函數(shù)里面定義了一個局部變量唱矛,在函數(shù)外部無法訪問到這個局部變量
}
alert(v); //彈出:20
訪問到。
</script>
<script type="text/javascript">
//因為v是全局變量井辜,所以這里仍然可以訪問到绎谦。
alert(v); //彈出:20
</script>
在函數(shù)內(nèi)部所有末定義直接賦值的變量自動聲明為擁有全局作用域,例如:
function sum(){
var v = 20;
b = 10;
alert(v);
}
sum(); //20
alert(b); //10
alert(v); //腳本錯誤
JavaScript中有沒有塊級作用域粥脚?
<script type="text/javascript">
var m = 5;
if(m == 5){
var n = 10;
}
alert(n); //輸出10- JavaScript的作用域是按照函數(shù)來劃分的JavaScript沒有塊級作用域
</script>
當(dāng)一個函數(shù)創(chuàng)建后窃肠,它的作用域鏈會被創(chuàng)建此函數(shù)的作用域中可訪問的數(shù)據(jù)對象填充。
function add(num1,num2) {
var sum = num1 + num2;
return sum;
}
在函數(shù)add創(chuàng)建時阿逃,它的作用域鏈中會填入一個全局對象铭拧,該全局對象包含了所有全局變量,
我們可以看到恃锉,由于函數(shù)作用域的特性搀菩,局部變量在整個函數(shù)體始終是由定義的,我們可以將變量聲明”提前“到函數(shù)體頂部破托,同時變量初始化還在原來位置肪跋。
var scope="global";
function t(){
console.log(scope); // 是"undefined",而不是 "global"
var scope="local"
console.log(scope); //是"local"
}
t();
當(dāng)執(zhí)行s時土砂,將創(chuàng)建函數(shù)s的執(zhí)行環(huán)境(調(diào)用對象),并將該對象置于鏈表開頭州既,然后將函數(shù)t的調(diào)用對象鏈接在之后,最后是全局對象萝映。然后從鏈表開頭尋找變量name,很明顯name是"slwy"吴叶,但執(zhí)行ss()時,name是 tlwy序臂。
name="lwy";
function t(){
var name="tlwy";
function s(){
var name="slwy";
console.log(name);
}
function ss(){
console.log(name);
}
s();
ss();
}
t();
閉包
閉包是指有權(quán)訪問另一個函數(shù)作用域中的變量的函數(shù)
<script type="text/javascript">
function createSumFunction(num1, num2){
return function () {
return num1 + num2;
};
}
var sumFun = createSumFunction(3, 4);
var sum = sumFun();
alert(sum);
</script>
閉包中使用的局部變量的值蚌卤,一定是局部變量的最后的值实束。
function a(){
var n = 0;
function inc() {
n++;
console.log(n);
}
inc();
inc();
}
a(); //控制臺輸出1,再輸出2
常見的陷阱逊彭,以為輸出 0~9 咸灿,萬萬沒想到輸出10個10
function createFunctions(){
var result = new Array();
for (var i=0; i < 10; i++){
result[i] = function(){
return i;
};
}
return result;
}
var funcs = createFunctions();
for (var i=0; i < funcs.length; i++){
console.log(funcs[i]());
}
上面的解釋就是:
var result = new Array(), i;
result[0] = function(){ return i; }; //沒執(zhí)行函數(shù),函數(shù)內(nèi)部不變侮叮,不能將函數(shù)內(nèi)的i替換避矢!
result[1] = function(){ return i; }; //沒執(zhí)行函數(shù),函數(shù)內(nèi)部不變囊榜,不能將函數(shù)內(nèi)的i替換审胸!
...
result[9] = function(){ return i; }; //沒執(zhí)行函數(shù),函數(shù)內(nèi)部不變锦聊,不能將函數(shù)內(nèi)的i替換歹嘹!
i = 10;
funcs = result;
result = null;
console.log(i); // funcs[0]()就是執(zhí)行 return i 語句,就是返回10
console.log(i); // funcs[1]()就是執(zhí)行 return i 語句孔庭,就是返回10
...
console.log(i); // funcs[9]()就是執(zhí)行 return i 語句尺上,就是返回10
閉包就是一個函數(shù)引用另外一個函數(shù)的變量,因為變量被引用著所以不會被回收圆到,因此可以用來封裝一個私有變量怎抛。這是優(yōu)點也是缺點,不必要的閉包只會徒增內(nèi)存消耗芽淡!另外使用閉包也要注意變量的值是否符合你的要求马绝,因為他就像一個靜態(tài)私有變量一樣。