深入淺析javascript中的作用域(推薦)
所謂的作用域,可以簡(jiǎn)單理解為一個(gè)可以讀、寫的范圍(區(qū)域),有些js經(jīng)驗(yàn)的同學(xué)可能會(huì)說(shuō):"js沒有塊級(jí)作用域",js除了全局作用域外,只有函數(shù)可以創(chuàng)建作用域。作用域的一個(gè)好處就是可以隔離變量。
我們通過(guò)一些例子來(lái)幫助我們理解js中的作用域。
alert(a); var a = 1;
如果對(duì)作用域一點(diǎn)不了解的同學(xué)可能會(huì)說(shuō) alert的是1或者報(bào)錯(cuò);但實(shí)際上是undefined;
說(shuō)到這里,我們首先說(shuō)一下js逐行解析代碼之前做的一些準(zhǔn)備工作,
js在逐行讀代碼之前,會(huì)做一些“預(yù)解析”工作,會(huì)先提前找到一些”小東西”,當(dāng)然”js解析器“不會(huì)隨便找一些數(shù)據(jù)的,它會(huì)根據(jù)var,function,參數(shù)來(lái)找。
”js解析器“它比較”懶“,在正式運(yùn)行代碼之前都會(huì)給var聲明的變量賦值為undefined,也就是var a = undefined;會(huì)把整個(gè)函數(shù)看作一個(gè)代碼塊,不去管里邊有多少代碼。參數(shù)等到后邊例子中會(huì)說(shuō)。
當(dāng)所有準(zhǔn)備工作都做好后,“JS解析器”就開始逐行執(zhí)行代碼了,現(xiàn)在我們來(lái)分析開始的這個(gè)例子就很容易明白為什么是undefined了。
再來(lái)看下邊這個(gè)例子
alert(a); var a = 1; alert(a); var a = 2; alert(a);
我們來(lái)一點(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);
我們依然來(lái)一點(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)用,略過(guò);
第五行 alert:1;
第六行 a = 3;
第七行 alert:3
第八行 函數(shù)沒有調(diào)用,略過(guò);
第九行 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ù)的作用域的上一級(jí)作用域去尋找a(作用域上下級(jí)關(guān)系的確定就看函數(shù)是在哪個(gè)作用域下創(chuàng)建的,在哪個(gè)作用域下創(chuàng)建,就是哪個(gè)作用域的下級(jí)),此時(shí)函數(shù)的上一級(jí)是全局作用域,在全局作用域中,a = 1,所以此時(shí)第三行 alert:1,接著第四行,a = 2賦值,依然是函數(shù)作用域中沒有a, 所以在上一級(jí)作用域,也就是全局作用域中找到a,修改全局作用域中的a, 所以會(huì)使全局作用域中的a = 2, 因此第七行 alert:2;
這點(diǎn)要理解清楚,注意有無(wú)var的區(qū)別。
接著來(lái):
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ū)別,別混淆了。
再來(lái)一個(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)是這門語(yǔ)言的獨(dú)到之處,這部分歸功于他們帶來(lái)的靈活性。每個(gè)函數(shù)有不同的變量上下文和作用域。這些概念是javascript中一些強(qiáng)大的設(shè)計(jì)模式的后盾。然而這也給開發(fā)人員帶來(lái)很大困惑。下面全面揭示了javascript中的上下文和作用域的不同,以及各種設(shè)計(jì)模式如何使用他們。
上下文 vs 作用域
首先需要澄清的問題是上下文和作用域是不同的概念。多年來(lái)我注意到許多開發(fā)者經(jīng)常將這兩個(gè)術(shù)語(yǔ)混淆,錯(cuò)誤的將一個(gè)描述為另一個(gè)。平心而論,這些術(shù)語(yǔ)變得非?;靵y不堪。
每個(gè)函數(shù)調(diào)用都有與之相關(guān)的作用域和上下文。從根本上說(shuō),范圍是基于函數(shù)(function-based)而上下文是基于對(duì)象(object-based)。換句話說(shuō),作用域是和每次函數(shù)調(diào)用時(shí)變量的訪問有關(guān),并且每次調(diào)用都是獨(dú)立的。上下文總是關(guān)鍵字 this 的值,是調(diào)用當(dāng)前可執(zhí)行代碼的對(duì)象的引用。
以上所述是小編給大家介紹的javascript中的作用域(推薦),希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
基于javascript實(shí)現(xiàn)彩票隨機(jī)數(shù)生成(簡(jiǎn)單版)
這篇文章主要介紹了基于javascript實(shí)現(xiàn)彩票隨機(jī)數(shù)生成的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-01-01layui的數(shù)據(jù)表格+springmvc實(shí)現(xiàn)搜索功能的例子
今天小編就為大家分享一篇layui的數(shù)據(jù)表格+springmvc實(shí)現(xiàn)搜索功能的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2019-09-09javascript結(jié)合ajax讀取txt文件內(nèi)容
這篇文章主要介紹了javascript結(jié)合ajax讀取txt文件內(nèi)容,方法非常簡(jiǎn)單,很實(shí)用,這里推薦給大家2014-12-12webpack配置proxyTable時(shí)pathRewrite無(wú)效的解決方法
這篇文章主要介紹了webpack配置proxyTable時(shí)pathRewrite無(wú)效的解決方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12基于Bootstrap的標(biāo)簽頁(yè)組件及bootstrap-tab使用說(shuō)明
這篇文章主要介紹了基于Bootstrap的標(biāo)簽頁(yè)組件及bootstrap-tab使用說(shuō)明,需要的朋友可以參考下2017-07-07