作用域、執行環境、閉包

今天開始一個小系列,我們從作用域開始,分別講述作用域、作用域鏈、執行環境,最終爲了學習理解JavaScript中一個很經典的概念:閉包

閉包是JavaScript中比較高級的概念和技巧,也是難理解的部分,必須熟練掌握函數表達式、作用域、變量的生存週期等概念後,才能掌握閉包的技巧。

作用域

我們已經知道了變量的概念,不管變量是基本數據類型還是引用類型,其都有一個作用範圍,稱之爲作用域,超出該變量的作用域,則不能被訪問,否則將會異常。如果該變量能被所有代碼訪問,稱之爲全局變量,其作用域爲整個代碼環境,反之爲局部變量,其作用域爲局部。可以將作用域的機制想象爲行政管轄範圍:縣長只能管轄整個縣、而市長可以管轄整個市、省長可以管轄整個省。

我們先來看以下代碼:

var name=""張三";

function setname(){

name="李四";

}

function showname(){

alert(name);

}

showname();      //顯示“張三”

setname();

showname();      //顯示“李四”

分析以上代碼,我們首先聲明瞭一個變量name並給其賦值爲“張三”,由於該變量的聲明不在任何函數內,因此其爲全局變量,作用域爲全局環境,可在整個代碼中對其訪問,所以可以在函數setname()對其改寫,並在函數showname()中對其訪問。

接下來對代碼做如下修改:

function setname(){

var name="李四";

alert(name);

}

function showname(){

alert(name);

}

showname();      //顯示空

setname();       //顯示“李四”

showname();      //顯示空

我們把變量name的聲明移至函數setname()內部,因此name的作用域範圍只是函數setname()內部,而在函數showname()中訪問不到變量name,因此顯示爲空。

繼續看以下的代碼:

function setname(){

var name="李四";

alert(name);

}

function setothername(){

var name="張三";

alert(name);

}

setname();             //顯示“李四”

setothername();       //顯示“張三”

雖然在函數setname()和setothername()都聲明瞭name變量,但由於兩個變量name的作用域均爲函數內部,因此這兩個變量name僅僅是名稱相同而已,實際上是完全不同的兩個變量,具有了不同的值。

接下來我們看一個較複雜的例子,函數內嵌套函數,可以更好的詮釋變量聲明的位置如何決定其所擁有的作用域:

var name="張三";

function changename(othername){

function swapname(){

var tempname=othername;

othername=name;

name=tempname;

//此處可以訪問name、tempname、othername

}

swapname();

//此處可以訪問name、othername,但不能訪問tnepname

}

changename("李四");

alert(name);      //顯示“李四”

//此處僅可訪問name

分析以上代碼,這是個改變姓名的函數,首先我們聲明瞭全局變量name,其能被所有代碼訪問,接下來聲明函數changename(),其傳入參數爲othername,因此函數changename()可以訪問name、othername兩個變量,在函數changename()中又聲明瞭函數swapname(),在其內部又聲明瞭局部變量tempname,所以函數swapname()可以訪問name、othername、tempname三個變量。但變量tempname不能被函數swapname()以外的代碼訪問,同樣傳入參數othername也不能被函數changename()以外的代碼訪問。

下一講我們將學習執行環境、作用域鏈。

歡迎加入技術QQ交流羣:364595326


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章