深入淺析javascript中的作用域(推薦)
所謂的作用域,可以簡單理解為一個(gè)可以讀、寫的范圍(區(qū)域),有些js經(jīng)驗(yàn)的同學(xué)可能會(huì)說:"js沒有塊級作用域",js除了全局作用域外,只有函數(shù)可以創(chuàng)建作用域。作用域的一個(gè)好處就是可以隔離變量。
我們通過一些例子來幫助我們理解js中的作用域。
alert(a); var a = 1;
如果對作用域一點(diǎn)不了解的同學(xué)可能會(huì)說 alert的是1或者報(bào)錯(cuò);但實(shí)際上是undefined;
說到這里,我們首先說一下js逐行解析代碼之前做的一些準(zhǔn)備工作,
js在逐行讀代碼之前,會(huì)做一些“預(yù)解析”工作,會(huì)先提前找到一些”小東西”,當(dāng)然”js解析器“不會(huì)隨便找一些數(shù)據(jù)的,它會(huì)根據(jù)var,function,參數(shù)來找。
”js解析器“它比較”懶“,在正式運(yùn)行代碼之前都會(huì)給var聲明的變量賦值為undefined,也就是var a = undefined;會(huì)把整個(gè)函數(shù)看作一個(gè)代碼塊,不去管里邊有多少代碼。參數(shù)等到后邊例子中會(huì)說。
當(dāng)所有準(zhǔn)備工作都做好后,“JS解析器”就開始逐行執(zhí)行代碼了,現(xiàn)在我們來分析開始的這個(gè)例子就很容易明白為什么是undefined了。
再來看下邊這個(gè)例子
alert(a); var a = 1; alert(a); var a = 2; alert(a);
我們來一點(diǎn)點(diǎn)分析這個(gè)
首先 ”預(yù)解析“: 解析器會(huì)找var
讀到第二行時(shí) a = undefined;
讀到第四行時(shí) 依然 a = undefined;
正式逐行執(zhí)行代碼:
第一行 alert:undefined
第二行 a = 1;
第三行 alert:1;
第五行 alert:2
接著看下邊這個(gè)例子
alert(a);
var a = 1;
alert(a);
function a (){ alert(2); }
alert(a);
var a = 3;
alert(a);
function a (){ alert(4); }
alert(a);
我們依然來一點(diǎn)點(diǎn)分析這個(gè)
首先 ”預(yù)解析“: 解析器會(huì)找var function;
讀到第二行時(shí) a = undefined;
讀到第四行時(shí) a = function a (){ alert(2);} //所有的函數(shù),在正式運(yùn)行代碼之前,都是整個(gè)函數(shù)塊;變量遇到重名的,只留一個(gè)變量,如果變量和函數(shù)重名,就只留下函數(shù)。
讀到第六行時(shí),a = function a (){ alert(2);}
讀到第八行時(shí),a = function a (){ alert(4);}
正式逐行執(zhí)行代碼:
第一行 alert: function a (){ alert(4);}
第二行 a = 1; //表達(dá)式可以修改預(yù)解析的值!
第三行 alert:1;
第四行 函數(shù)沒有調(diào)用,略過;
第五行 alert:1;
第六行 a = 3;
第七行 alert:3
第八行 函數(shù)沒有調(diào)用,略過;
第九行 alert:3
如圖所示:

繼續(xù)看例子:
var a = 1;
function fn1(){
alert(a); //undefined
var a = 2;
}
fn1();
alert(a); //1
首先 ”預(yù)解析“: 解析器會(huì)找var function
讀到第一行時(shí) a = undefined;
讀到第二行時(shí) fn1 = function fn1 (){alert(2);var a = 2;}
正式逐行執(zhí)行代碼: 第一行 a = 1;
第六行 函數(shù)調(diào)用,進(jìn)入函數(shù)作用域 在函數(shù)作用域內(nèi)依舊是先預(yù)解析,再逐行執(zhí)行
函數(shù)內(nèi)預(yù)解析:a = undefined;
執(zhí)行:alert:undefined;
a = 2; //此時(shí)的a僅為函數(shù)作用域中的a,不會(huì)影響全局中的a
函數(shù)執(zhí)行完畢,回到全局作用域;
第七行 alert:1;
繼續(xù):
var a = 1;
function fn1(){
alert(a); //1
a = 2;
}
fn1();
alert(a); //2
這個(gè)例子上邊那個(gè)例子唯一的區(qū)別就是函數(shù)中的a沒有var,只分析其中關(guān)鍵的地方
在函數(shù)作用域中 第三行alert(a),由于函數(shù)中沒有var a,所以"解析器"會(huì)到函數(shù)的作用域的上一級作用域去尋找a(作用域上下級關(guān)系的確定就看函數(shù)是在哪個(gè)作用域下創(chuàng)建的,在哪個(gè)作用域下創(chuàng)建,就是哪個(gè)作用域的下級),此時(shí)函數(shù)的上一級是全局作用域,在全局作用域中,a = 1,所以此時(shí)第三行 alert:1,接著第四行,a = 2賦值,依然是函數(shù)作用域中沒有a, 所以在上一級作用域,也就是全局作用域中找到a,修改全局作用域中的a, 所以會(huì)使全局作用域中的a = 2, 因此第七行 alert:2;
這點(diǎn)要理解清楚,注意有無var的區(qū)別。
接著來:
var a = 1;
function fn1(a){
alert(a); //undefined
a = 2;
}
fn1();
alert(a); // 1
這個(gè)例子和上一個(gè)的區(qū)別就是多了個(gè)參數(shù),參數(shù)的作用相當(dāng)于局部變量,也就是在函數(shù)中預(yù)解析會(huì)有var a = undefined,所以第三行 alert:undefined,第四行 a = 2 改的是函數(shù)作用域中的a,不影響全局中的a,第七行alert:1;
接著:
var a = 1;
function fn1(a){
alert(a); // 1
a = 2;
}
fn1(a);
alert(a); // 1
這個(gè)例子又與上一個(gè)有些區(qū)別,在第六行函數(shù)調(diào)用時(shí)傳了個(gè)實(shí)參進(jìn)去,第六行函數(shù)實(shí)參的a是全局變量a = 1的1,函數(shù)執(zhí)行時(shí),第二行 a = 1,所以第三行alert:1,第七行alert:1。
注意這幾個(gè)例子之間的區(qū)別,別混淆了。
再來一個(gè):
var a = 1;
function en(){
var a = 2;
fn();
}
function fn(){
alert(a); //1
}
en();
fn中的a未聲明,要到創(chuàng)建這個(gè)函數(shù)的那個(gè)作用域中取值——是“創(chuàng)建”,而不是“調(diào)用”這個(gè)函數(shù)的作用域中。
PS:JavaScript中的作用域和上下文概念
javascript中的作用域(scope)和上下文(context)是這門語言的獨(dú)到之處,這部分歸功于他們帶來的靈活性。每個(gè)函數(shù)有不同的變量上下文和作用域。這些概念是javascript中一些強(qiáng)大的設(shè)計(jì)模式的后盾。然而這也給開發(fā)人員帶來很大困惑。下面全面揭示了javascript中的上下文和作用域的不同,以及各種設(shè)計(jì)模式如何使用他們。
上下文 vs 作用域
首先需要澄清的問題是上下文和作用域是不同的概念。多年來我注意到許多開發(fā)者經(jīng)常將這兩個(gè)術(shù)語混淆,錯(cuò)誤的將一個(gè)描述為另一個(gè)。平心而論,這些術(shù)語變得非?;靵y不堪。
每個(gè)函數(shù)調(diào)用都有與之相關(guān)的作用域和上下文。從根本上說,范圍是基于函數(shù)(function-based)而上下文是基于對象(object-based)。換句話說,作用域是和每次函數(shù)調(diào)用時(shí)變量的訪問有關(guān),并且每次調(diào)用都是獨(dú)立的。上下文總是關(guān)鍵字 this 的值,是調(diào)用當(dāng)前可執(zhí)行代碼的對象的引用。
以上所述是小編給大家介紹的javascript中的作用域(推薦),希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
相關(guān)文章
javascript瀑布流式圖片懶加載實(shí)例解析與優(yōu)化
這篇文章主要針對javascript瀑布流式圖片懶加載實(shí)例進(jìn)行解析與優(yōu)化,感興趣的小伙伴們可以參考一下2016-02-02
JS.getTextContent(element,preformatted)使用介紹
JS.getTextContent獲取標(biāo)簽的文字想必大家并不陌生吧,下面為大家介紹下具體的使用方法,感興趣的朋友可以參考下2013-09-09
利用js動(dòng)態(tài)添加刪除table行的示例代碼
本篇文章主要是對利用js動(dòng)態(tài)添加刪除table行的示例代碼進(jìn)行了介紹,需要的朋友可以過來參考下,希望對大家有所幫助2013-12-12
javascript 中事件冒泡和事件捕獲機(jī)制的詳解
這篇文章主要介紹了javascript 中事件冒泡和事件捕獲機(jī)制的詳解的相關(guān)資料,網(wǎng)上的相關(guān)資料有很多,但是講的不是多清楚,通過本文希望能讓大家理解掌握,需要的朋友可以參考下2017-09-09
關(guān)于Stream和Buffer的相互轉(zhuǎn)換詳解
這篇文章主要給大家介紹了關(guān)于Stream和Buffer相互轉(zhuǎn)換的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧。2017-07-07
JavaScript彈簧振子超簡潔版 完全符合能量守恒,胡克定理
完全符合能量守恒,胡克定理的JavaScript彈簧振子(超簡潔版,超越第一版!)2009-10-10
Javascript 網(wǎng)頁水印(非圖片水印)實(shí)現(xiàn)代碼
在一些B/S結(jié)構(gòu)的應(yīng)用系統(tǒng)中,有很多頁面是需要有水印的。常見的就是公文系統(tǒng)、合同系統(tǒng)等。2010-03-03

