摘要:當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí),會創(chuàng)建變量對象的一個(gè)作用域鏈,作用域鏈的用途,是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。作用域鏈的下一個(gè)變量對象則來自下一個(gè)包含環(huán)境。
前言
JavaScript中變量是松散類型,這樣它只在特定的時(shí)間內(nèi)用于保存一個(gè)特定的值。由于不存在定義某個(gè)變量必須要保存何種數(shù)據(jù)類型的規(guī)則,變量的值和其數(shù)據(jù)類型可以在腳本的生命周期內(nèi)改變。
1. 基本類型和引用類型的值JavaScript中變量可能包含兩種不同類型的值: 基本類型和引用類型。 基本類型值指的是簡單的數(shù)據(jù)段,而引用類型指的是那些可能多個(gè)值構(gòu)成的對象。
JavaScript中有5種基本類型的值:Number, String, Null,Undefined, Boolean。這5種基本類型是按值訪問的,因?yàn)?strong>可以操作保存在變量中的實(shí)際的值。
引用類型的值是保存在內(nèi)存中的對象。 與其他語言不同, JavaScript不允許直接訪問內(nèi)存中的位置, 也就是說不能直接操作對象的內(nèi)存空間。 在操作對象時(shí), 實(shí)際上是操作對象的引用而不是實(shí)際的對象。因此,引用類型的值是按引用訪問的。
注意: 當(dāng)復(fù)制保存著對象的某個(gè)變量時(shí), 操作的是對象的引用。 但在為對象添加屬性的時(shí)候,操作的實(shí)際的對象
1.1 動態(tài)的屬性定義基本類型值和引用類型值得方式是類似的:創(chuàng)建一個(gè)變量并為該變量賦值。對于引用類型的值來說,我們可以為其添加屬性和方法,也可以改變和刪除其屬性和方法。但是基本類型的值卻不行。
var person = new Object() person.name = "Nicholas" alert(person.name) //"Nicholas"
如上,我們創(chuàng)建一個(gè)對象,并保存在person。然后為該對象添加一個(gè)name屬性,最后通過person.name可以訪問這個(gè)新屬性,如果對象不被銷毀或者這個(gè)屬性不被刪除,則這個(gè)屬性將一直存在。
如果我們給基本類型的值添加屬性,雖然不會導(dǎo)致錯(cuò)誤,但是這樣是不合理的:
var name = "Nicholas" name.age = 27 alert(name.age) //undefined1.2 復(fù)制變量值
除了保存的方式不同,從一個(gè)變量向另一個(gè)變量復(fù)制基本類型值和引用類型值時(shí)也存在不同。如果一個(gè)變量向另一個(gè)變量復(fù)制基本類型的值,會在變量對象上創(chuàng)建一個(gè)新值,然后把該值復(fù)制到為新變量分配的位置上。
var num1 = 5 var num2 = num1
當(dāng)從一個(gè)變量向另一個(gè)變量復(fù)制引用類型的值時(shí),同樣也會將存儲在變量對象中的值復(fù)制一份放到為新變量分配的空間中。不同的是,這個(gè)值得副本實(shí)際上是一個(gè)指針,而這個(gè)指針指向存儲在堆中的一個(gè)對象。復(fù)制操作結(jié)束后,兩個(gè)變量實(shí)際上將引用同一個(gè)對象。因此,改變其中一個(gè)變量,就會影響另一個(gè)變量:
var o1 = new Object() var o2 = o2 o1.name = "Nicholas" alert(o2.name) //Nicholas1.3 傳遞參數(shù)
ECMAscript中所有的函數(shù)參數(shù)都是按值傳遞的,也就是說,把函數(shù)外部的值復(fù)制給函數(shù)內(nèi)部參數(shù),就和把值從一個(gè)變量復(fù)制到另一個(gè)變量一樣?;绢愋偷膫鬟f如同基本類型變量的復(fù)制一樣,而引用類型值得傳遞如何引用類型變量的復(fù)制一樣。
在向參數(shù)傳遞基本類型的值時(shí),被傳遞的值會被復(fù)制給一個(gè)局部變量(即命名參數(shù),就是arguments對象中的一個(gè)元素)。在向參數(shù)傳遞引用類型的值時(shí),會把這個(gè)值在內(nèi)存中的地址復(fù)制一個(gè)給局部變量,因此這個(gè)局部變量的變化會發(fā)生在外部。但是這樣總會感覺參數(shù)還是通過按引用傳遞的。下面這個(gè)例子可以證明是按值傳遞:
var person = new Object() function setName(obj) { obj.name = "Nicholas" obj = new Object() obj.name = "Greg" } setName(person)
如果person是按引用傳遞的,那么person會被改成一個(gè)新對象,但是當(dāng)你繼續(xù)訪問person.name的時(shí)候返回的是"Nicholas"。這說明即使在函數(shù)內(nèi)部修改了參數(shù)的值,但是原始的引用仍然保持未變。實(shí)際上當(dāng)函數(shù)內(nèi)部重寫obj時(shí),這個(gè)變量引用的就是一個(gè)局部對象了,而這個(gè)局部對象會在函數(shù)執(zhí)行完畢后銷毀。
2. 執(zhí)行環(huán)境和作用域執(zhí)行環(huán)境定義了變量或函數(shù)有權(quán)訪問的其他數(shù)據(jù),決定了它們各自的行為。每個(gè)執(zhí)行環(huán)境都有與之關(guān)聯(lián)的變量對象。執(zhí)行環(huán)境中定義的所有變量和函數(shù)都保存在這個(gè)對象中。雖然我們編寫的代碼無法訪問這個(gè)對象,但解析器在處理數(shù)據(jù)時(shí)會在后臺使用它。
每個(gè)函數(shù)都有自己的執(zhí)行環(huán)境,當(dāng)執(zhí)行流進(jìn)入一個(gè)函數(shù)時(shí),函數(shù)的環(huán)境就會被推入一個(gè)環(huán)境棧中,而在函數(shù)執(zhí)行之后,棧將其環(huán)境彈出,把控制權(quán)返回給之前的執(zhí)行環(huán)境。
當(dāng)代碼在一個(gè)環(huán)境中執(zhí)行時(shí),會創(chuàng)建變量對象的一個(gè)作用域鏈,作用域鏈的用途,是保證對執(zhí)行環(huán)境有權(quán)訪問的所有變量和函數(shù)的有序訪問。作用域鏈的前端,始終都是當(dāng)前執(zhí)行代碼所在的環(huán)境的變量對象。如果這個(gè)環(huán)境是函數(shù),則將其活動對象作為變量對象?;顒訉ο笤谧铋_始時(shí)只包含一個(gè)變量,即argument對象。作用域鏈的下一個(gè)變量對象則來自下一個(gè)包含環(huán)境。這樣一直延續(xù)到全局環(huán)境。
標(biāo)識符解析是沿著作用域鏈一級一級的搜索標(biāo)識符的過程。
2.1 延長作用域鏈有些語句可以在作用域鏈的前端臨時(shí)增加一個(gè)變量對象, 該變量對象會在代碼執(zhí)行后被移除。在兩種情況下會發(fā)生這種現(xiàn)象,具體來說就是當(dāng)執(zhí)行流進(jìn)入下列任何一個(gè)語句時(shí),作用域鏈會得到加長。
try-catch的catch塊
with語句
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/93046.html
前言 JavaScript中有一個(gè)被稱為作用域(Scope)的特性。雖然對于許多新手開發(fā)者來說,作用域的概念并不是很容易理解,本文我會盡我所能用最簡單的方式來解釋作用域和作用域鏈,希望大家有所收獲! 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客 作用域(Scope) 1.什么是作用域 作用域是在運(yùn)行時(shí)代碼中的某些特定部分中變量,函數(shù)和對象的可訪問性。換句話說,作用域決定了代碼區(qū)塊中變量和其他資源的可見...
前言 JavaScript中有一個(gè)被稱為作用域(Scope)的特性。雖然對于許多新手開發(fā)者來說,作用域的概念并不是很容易理解,本文我會盡我所能用最簡單的方式來解釋作用域和作用域鏈,希望大家有所收獲! 想閱讀更多優(yōu)質(zhì)文章請猛戳GitHub博客 作用域(Scope) 1.什么是作用域 作用域是在運(yùn)行時(shí)代碼中的某些特定部分中變量,函數(shù)和對象的可訪問性。換句話說,作用域決定了代碼區(qū)塊中變量和其他資源的可見...
摘要:一旦函數(shù)執(zhí)行完成,其就會從作用域鏈頂部移除,并且執(zhí)行權(quán)會返回到函數(shù)。攀爬作用域鏈當(dāng)不同執(zhí)行上下文之間存在變量命名沖突,可以通過攀爬作用域鏈解決從頂部到底部。 一、作用域 在 JavaScript 中, 作用域(scope,或譯有效范圍)就是變量和函數(shù)的可訪問范圍,即作用域控制著變量和函數(shù)的可見性和生命周期 二、全局/局部作用域 2.1 全局作用域(Global Scope) (1)不...
摘要:全局作用域局部作用域局部作用域全局作用域局部作用域塊語句沒有塊級作用域塊級聲明包括和,以及和循環(huán),和函數(shù)不同,它們不會創(chuàng)建新的作用域。局部作用域只在該函數(shù)調(diào)用執(zhí)行期間存在。 一、什么是作用域? 作用域是你的代碼在運(yùn)行時(shí),各個(gè)變量、函數(shù)和對象的可訪問性。(可產(chǎn)生作用的區(qū)域) 二、JavaScript中的作用域 在 JavaScript 中有兩種作用域 全局作用域 局部作用域 當(dāng)變量定...
摘要:并且作用域鏈也確定了在當(dāng)前上下文中查找標(biāo)識符后返回的值。為了具象化分析問題,我們可以假設(shè)作用域鏈?zhǔn)且粋€(gè)數(shù)組,數(shù)組成員有一系列變量對象組成。注意,所有作用域鏈的最末端都為全局變量對象。所以作用域作用域鏈都是在當(dāng)前運(yùn)行環(huán)境內(nèi)代碼執(zhí)行前就確定了。 什么是作用域(Scope)? 作用域產(chǎn)生于程序源代碼中定義變量的區(qū)域,在程序編碼階段就確定了。javascript 中分為全局作用域(Global...
閱讀 2238·2021-09-24 10:31
閱讀 3889·2021-09-22 15:16
閱讀 3411·2021-09-22 10:02
閱讀 1026·2021-09-22 10:02
閱讀 1842·2021-09-08 09:36
閱讀 1988·2019-08-30 14:18
閱讀 617·2019-08-30 10:51
閱讀 1881·2019-08-29 11:08