您好,登錄后才能下訂單哦!
小編給大家分享一下Javascript中作用域的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
我們主要來(lái)看看Javascript中變量作用域的問(wèn)題。主要涉及以下內(nèi)容 :
參數(shù)傳遞的問(wèn)題
什么是作用域和作用域鏈
塊級(jí)作用域
延長(zhǎng)作用域鏈
參數(shù)傳遞的問(wèn)題
在Javascript中所有的參數(shù)傳遞都是按值傳遞的。也就是說(shuō)把函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部的參數(shù),就和把值從一個(gè)變量復(fù)制到另一個(gè)變量一樣?;绢愋椭档膫鬟f如同基本類型變量的復(fù)制一樣,而引用類型值的傳遞,就如同引用類型變量的復(fù)制一樣。
—— 《Javascript 高級(jí)程序設(shè)計(jì)》 第三版
function addTen(num) { num += 10; return num; } var count = 20; var result = addTen(count); alert(count) // 20 alert(result) // 30
我想關(guān)于值類型的傳遞應(yīng)該很簡(jiǎn)單,所以我們就不多說(shuō)了,重點(diǎn)來(lái)看看引用類型的值傳遞。
function setName(person) { person.name = "Jesse"; } var person = new Object(); setName(person); alert(person.name); //Jesse
這個(gè)函數(shù)把我們外部對(duì)象的值也一起改變了,這一點(diǎn)和C#也是一樣的。因?yàn)楹瘮?shù)里面的person所指向的地址和外部person所指向的地址是一樣的。下面的行為也是和C#一樣的,即如果在函數(shù)內(nèi)容把參數(shù)指向另外一個(gè)對(duì)象,不會(huì)對(duì)外部對(duì)象產(chǎn)生影響 。
function setName(person) { person.name="Jesse" person = new Object(); person.name = "Another Jesse"; } var person = new Object(); setName(person); alert(person.name); //Jesse
關(guān)于引用類型的拷貝,給初學(xué)者一張圖解。
在堆中分配一塊空間給person對(duì)象,并在棧中保存person在堆中的址址引用
復(fù)制堆中person的地址引用給person2(同樣是在棧中)
new Person()再次在堆中分配一塊空間給person2對(duì)象,然后將棧中person2指向這個(gè)新的地址。
以后對(duì)person2的更改不會(huì)對(duì)person產(chǎn)生影響
什么是作用域和作用域鏈
我們知道在JavaScript中有局部變量和全局變量,某個(gè)函數(shù)里面的局部變量不能在另一個(gè)函數(shù)中被訪問(wèn)(暫且避開(kāi)閉包不談)。這就是作用域起的作用,因?yàn)樽兞恐辉谒诘哪莻€(gè)函數(shù)里面起作用。
每一個(gè)函數(shù)都有自己的執(zhí)行環(huán)境,而每一個(gè)執(zhí)行環(huán)境都有一個(gè)與之相關(guān)聯(lián)的變量對(duì)象, 這個(gè)環(huán)境中所有變量和函數(shù)就保存在這個(gè)變量中。除了函數(shù)有自己的執(zhí)行環(huán)境以外,我們還有一個(gè)最大的全局執(zhí)行環(huán)境,而我們所熟知的window就是這個(gè)全局執(zhí)行環(huán)境的變量對(duì)象,因?yàn)樗械娜肿兞亢秃瘮?shù)都是作為window的屬性和方法創(chuàng)建的。每個(gè)環(huán)境中的所有代碼執(zhí)行完后,該環(huán)境被隨之銷毀,保存在其中的所有變量和函數(shù)也隨之銷毀。對(duì)于全局執(zhí)行環(huán)境來(lái)說(shuō),關(guān)閉瀏覽器或者退出頁(yè)面,那么這個(gè)全局的執(zhí)行環(huán)境也就被銷毀了。
但是,我在這個(gè)函數(shù)里面是不是只能訪問(wèn)這個(gè)函數(shù)里面的變量呢?也許大家都知道,還有全局變量,全局變量可以被任意函數(shù)(Javascript沒(méi)有像public, private, protected 這樣的關(guān)鍵字),或者任意引入到頁(yè)面的js訪問(wèn)到。這個(gè)就是我們常說(shuō)的作用域鏈。作用域鏈的作用就是保證對(duì)執(zhí)行環(huán)境有權(quán)訪問(wèn)的所有變量和函數(shù)進(jìn)行有序訪問(wèn)。為什么說(shuō)有序訪問(wèn)呢? 來(lái)看一看下面這段代碼:
var color = "blue"; function alertColor() { var color = "red"; alert(color); } alertColor(); // red alert(color); // blue
大家知道如果局部變量和全局變量同名的話,全局變量會(huì)被覆蓋,但是也不是真正的覆蓋,只是在當(dāng)前這個(gè)函數(shù)里面被覆蓋而已,我們?cè)谕獠恳琅f可以正常使用的。這里就涉及到一個(gè)執(zhí)行環(huán)境有序訪問(wèn)的問(wèn)題。
作用域鏈的最前端永遠(yuǎn)是當(dāng)前執(zhí)行代碼所在環(huán)境的變量對(duì)象,對(duì)于我們的alertColor而言,就是它自己的活動(dòng)對(duì)象。 所有函數(shù)的活動(dòng)對(duì)象都包含一個(gè)初始值,那就是我們的arguments。而作用域鏈的下一個(gè)對(duì)象,來(lái)自包含的外部環(huán)境,一直延續(xù)到全局環(huán)境。所有函數(shù)的作用域鏈都可能延續(xù)到全局環(huán)境,這就是為什么全局變量可以在所有函數(shù)中訪問(wèn)的原因,并不是因?yàn)樗腥肿兞?,所以它就可以在所有函?shù)中訪問(wèn):) 并且,全局執(zhí)行環(huán)境的環(huán)境變量始終是作用域鏈的最后一個(gè)對(duì)象。
我們來(lái)看個(gè)復(fù)雜一點(diǎn)的例子:
var color = "blue"; function changeColor(){ var anotherColor = "red"; function swapColors(){ var tempColor = anotherColor; anotherColor = color; color = tempColor; // 這里面可以訪問(wèn)到 color, anotherColor, tempColor } // 這里只能訪問(wèn)到 anotherColor swapColors(); } // 這里只能訪問(wèn)到color changeColor();
在上面的代碼中,我們有3個(gè)執(zhí)行環(huán)境,全局環(huán)境、changeColor的局部執(zhí)行環(huán)境和swapColors的局部執(zhí)行環(huán)境。全局環(huán)境中只有一個(gè)變量color和一個(gè)函數(shù)changeColor()。changeColor中有一個(gè)變量anotherColor和一個(gè)函數(shù)swapColors(),但是它可以訪問(wèn)到全局環(huán)境中的color。swapColors中有一個(gè)局部變量tempColor,該變量只不管是在changeColor還是全局環(huán)境中都不能被訪問(wèn)到,然后在swapColors中可以訪問(wèn)到其它兩個(gè)環(huán)境中的所有變量,因?yàn)榱硗鈨蓚€(gè)環(huán)境都是它的父執(zhí)行環(huán)境。
我們可以發(fā)現(xiàn),作用域鏈?zhǔn)怯蓛?nèi)向外擴(kuò)展的,我們可以通過(guò)作用域訪問(wèn)外部環(huán)境的變量和函數(shù),但是外部環(huán)境中訪問(wèn)不到內(nèi)部環(huán)境的變量和函數(shù)。我們?cè)趕wapColors中用到了全局變量color,但是它也不是一下子就找到color的,它有一個(gè)由內(nèi)向外的查找過(guò)程:
在當(dāng)前執(zhí)行環(huán)境內(nèi)尋找叫color的局部變量,沒(méi)有找到,向上升一級(jí)
在父級(jí)執(zhí)行環(huán)境changeColor中去找叫color的變量,也沒(méi)有找到,再向上升一級(jí)
在changeColor的父級(jí)中找到了color變量,直接拿過(guò)來(lái)使用。
塊級(jí)作用域
因?yàn)橛兄鴫K級(jí)作用域(以花括號(hào)作為起始點(diǎn))的存在,C#中這樣的代碼是編譯不通過(guò)的。
static void Main(string[] args) { for(var i=0;i<=10;i++) { Console.Write(i); } Console.Write(i); }
我們?cè)趂or循環(huán)以外已經(jīng)訪問(wèn)不到i了。但是在Javascript情況就完全不一樣了。
for (var i = 0; i <= 10; i++) { // } alert(i); // 11
延長(zhǎng)作用域鏈
我們上面說(shuō)了,在Javascript中總共只有2種執(zhí)行環(huán)境:全局和局部執(zhí)行環(huán)境。但是我們可以用with和try-catch來(lái)延長(zhǎng)作用域,由于平常使用場(chǎng)景較少,我們就拿with來(lái)舉個(gè)例子好了。
function buildUrl() { var qs = "?debug=true"; with(location){ var url = href + qs; } return url; }
在with的作用下,location這個(gè)變量被加到了作用域的最前端,所以所有l(wèi)ocation下的變量和方法都可以在with的這個(gè)范圍內(nèi)訪問(wèn)了。
以上就是我們要講的作用域的內(nèi)容了,來(lái)總結(jié)一下吧:
值類型按值傳遞,引用類型按引用傳遞。傳遞的行業(yè)和用變量拷貝的行業(yè)是一樣的。
Javascript中有兩種執(zhí)行環(huán)境:全局和局部(函數(shù))
執(zhí)行環(huán)境內(nèi)有一個(gè)變量對(duì)象定義了該執(zhí)行環(huán)境下能訪問(wèn)的變量和函數(shù)
執(zhí)行環(huán)境可以由內(nèi)向外延伸一直延伸到全局的執(zhí)行環(huán)境
Javascript沒(méi)有塊級(jí)作用域
以上是“Javascript中作用域的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對(duì)大家有所幫助,如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道!
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。