摘要:編譯器遇到,會檢查當(dāng)前的作用域中是否有的聲明。引擎運(yùn)行時(shí)會查找當(dāng)前的作用域中是否有一個(gè)名字為的變量。與作用域判別失敗相關(guān),則代表了作用域判別成功,但對結(jié)果的操作是非法或不合理的。對象里的屬性會變成作用域里變量。
JavaScript的編譯
通常來說JavaScript是一門“動(dòng)態(tài)”或者“解釋執(zhí)行”語言,但事實(shí)上它是一門編譯語言,晦澀的編譯原理咱就不說了(我也不懂),直接說一下JavaScript的編譯情況。對于JavaScript來說,大部分情況下編譯發(fā)生在代碼執(zhí)行前幾微秒的時(shí)間內(nèi)。
最簡單的一段JavaScript的代碼:
var a = 2;
編譯器對于這行代碼會進(jìn)行兩個(gè)步驟的處理:
//變量聲明 var a; //賦值操作 a = 2;
這個(gè)過程中會涉及到變量提升的問題。
編譯器遇到var a,會檢查當(dāng)前的作用域中是否有a的聲明。如果有,那么就會忽略掉a的聲明,如果沒有就會在當(dāng)前的作用域中聲明一個(gè)新的變量,并命名為a。
接下來編譯器就把a(bǔ) = 2這條語句翻譯成機(jī)器代碼等待運(yùn)行。引擎運(yùn)行時(shí)會查找當(dāng)前的作用域中是否有一個(gè)名字為a的變量。如果有就使用;如果沒有,引擎會到上層的作用域中查找,直到全局作用域中。
區(qū)分RHS和LHSvar a = 2; //這里是一個(gè)LHS引用 console.log(a); //這里是一個(gè)RHS引用
乍一看LHS就是‘=’的左邊,RHS就是‘=’的右邊。但我對LHS的理解是我把值放到哪里,RHS是我去哪里找我要的值。為什么要區(qū)分RHS和LHS,因?yàn)樵谧兞窟€沒有聲明的時(shí)候,這兩種查詢的行為是不一樣的。
function foo(a){ console.log(a+b); b = a; } foo(2);
運(yùn)行時(shí),第一次對b進(jìn)行的是RHS的查詢,引擎在所有作用域中都找不到,最后會拋出一個(gè)ReferenceError的錯(cuò)誤。而對于b=a而言,b進(jìn)行的是LHS查詢,如果在全局作用域中都找不到,那么就會在全局作用域中創(chuàng)建一個(gè)變量b。(前提是代碼運(yùn)行在非嚴(yán)格模式)。
接下來,如果RHS查詢到了一個(gè)變量,但你嘗試對這個(gè)變量的值進(jìn)行不合理的操作。比如,對一個(gè)非函數(shù)類型的值進(jìn)行函數(shù)調(diào)用,那么引擎會拋出TypeError。
ReferenceError與作用域判別失敗相關(guān),TypeError則代表了作用域判別成功,但對結(jié)果的操作是非法或不合理的。
詞法作用域就是定義在詞法階段的作用域。更通俗的說法是詞法作用域是你書寫代碼的順序決定的。例如如下代碼:
function foo(a){ var b = a*2; function bar(c){ console.log(a,b,c); } bar(b*3); } foo(2);
在全局作用域中只有一個(gè)變量foo;在foo的作用域中有變量a,b和函數(shù)bar;在bar的作用域中有變量c。這種層層嵌套的關(guān)系是在書寫時(shí)就已經(jīng)決定了。
動(dòng)態(tài)作用域就是在程序運(yùn)行的時(shí)候才能確定的作用域。JavaScript中有兩種實(shí)現(xiàn)方式eval和with。但這兩種方式都會導(dǎo)致性能的下降,所以還是少用。
JavaScript中的eval函數(shù)可以接受一個(gè)字符串的參數(shù),并將其中的內(nèi)容視為好像在書寫的時(shí)候就存在于程序中這個(gè)位置一樣。例如如下代碼:
function foo(str,a){ eval(str); console.log(a,b); } var b = 2; foo("var b = 3;",1);//1,3
eval函數(shù)的參數(shù)是“var b = 3;”,這段代碼就會被當(dāng)做本來就在那里一樣。也就是會遮蔽全局作用域中的b變量。
withwith表面上是一種引用同一個(gè)對象不同屬性的快捷方式,但更重要的是它會創(chuàng)建一個(gè)新的作用域,例如如下代碼:
//with體現(xiàn)了訪問對象的快捷 var obj = { a:1, b:2, c:3 }; //不使用with obj.a = 2; obj.b = 3; obj.c = 4; //使用with with(obj){ a = 2; b = 3; c = 4; }
創(chuàng)建新的作用域可以看如下代碼:
function foo(obj){ with(obj){ a = 2; } } var o1 = { a:3 }; var o2 = { b:3 }; foo(o1); console.log(o1.a);//2 foo(o2); console.log(o2.a);//undefined console.log(a);//2,a暴露在全局作用域中
a為什么會暴露在全局作用域中?
當(dāng)執(zhí)行foo(o1)時(shí),因?yàn)槭褂昧藈ith,所以會創(chuàng)建一個(gè)全新的作用域,命名為o1。o1對象里的屬性會變成o1作用域里變量。當(dāng)執(zhí)行a=2時(shí),可以在o1的作用域中找到a,所以就修改了a的值。
當(dāng)執(zhí)行foo(o2)時(shí),o2的作用域中沒有a變量,所以會執(zhí)行LHS的查詢,最終會在全局作用局中聲明一個(gè)變量a,所以就導(dǎo)致了a暴露在全局作用域中。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/79841.html
摘要:作用域作用域是指程序源代碼中定義變量的區(qū)域。采用詞法作用域,也就是靜態(tài)作用域。而與詞法作用域相對的是動(dòng)態(tài)作用域,函數(shù)的作用域是在函數(shù)調(diào)用的時(shí)候才決定的。前面我們已經(jīng)說了,采用的是靜態(tài)作用域,所以這個(gè)例子的結(jié)果是。 JavaScript深入系列的第二篇,JavaScript采用詞法作用域,什么語言采用了動(dòng)態(tài)作用域?兩者的區(qū)別又是什么?還有一個(gè)略難的思考題,快來看看吧。 作用域 作用域是指...
摘要:也毫不例外,但在中作用域的特性與其他高級語言稍有不同,這是很多學(xué)習(xí)者久久難以理清的一個(gè)核心知識點(diǎn)。主要使用的是函數(shù)作用域。 關(guān)于作用域:About Scope 作用域是程序設(shè)計(jì)里的基礎(chǔ)特性,是作用域使得程序運(yùn)行時(shí)可以使用變量存儲值、記錄和改變程序的狀態(tài)。JavaScript 也毫不例外,但在 JavaScript 中作用域的特性與其他高級語言稍有不同,這是很多學(xué)習(xí)者久久難以理清的一個(gè)核...
摘要:講作用域鏈?zhǔn)紫纫獜淖饔糜蛑v起,下面是百度百科里對作用域的定義作用域在許多程序設(shè)計(jì)語言中非常重要。原文出處談?wù)務(wù)Z法里一些難點(diǎn)問題二 3) 作用域鏈相關(guān)的問題 作用域鏈?zhǔn)莏avascript語言里非常紅的概念,很多學(xué)習(xí)和使用javascript語言的程序員都知道作用域鏈?zhǔn)抢斫鈐avascript里很重要的一些概念的關(guān)鍵,這些概念包括this指針,閉包等等,它非常紅的另一個(gè)重要原因就...
摘要:全局作用域局部作用域局部作用域全局作用域局部作用域塊語句沒有塊級作用域塊級聲明包括和,以及和循環(huán),和函數(shù)不同,它們不會創(chuàng)建新的作用域。局部作用域只在該函數(shù)調(diào)用執(zhí)行期間存在。 一、什么是作用域? 作用域是你的代碼在運(yùn)行時(shí),各個(gè)變量、函數(shù)和對象的可訪問性。(可產(chǎn)生作用的區(qū)域) 二、JavaScript中的作用域 在 JavaScript 中有兩種作用域 全局作用域 局部作用域 當(dāng)變量定...
摘要:在中的應(yīng)用采用詞法作用域,也就是靜態(tài)作用域。那什么又是詞法作用域或者靜態(tài)作用域呢請繼續(xù)往下看靜態(tài)作用域與動(dòng)態(tài)作用域因?yàn)椴捎玫氖窃~法作用域函數(shù)的作用域在函數(shù)定義的時(shí)候就決定了。 開篇 當(dāng)我們在開始學(xué)習(xí)任何一門語言的時(shí)候,都會接觸到變量的概念,變量的出現(xiàn)其實(shí)是為了解決一個(gè)問題,為的是存儲某些值,進(jìn)而,存儲某些值的目的是為了在之后對這個(gè)值進(jìn)行訪問或者修改,正是這種存儲和訪問變量的能力將狀態(tài)給...
閱讀 2222·2021-09-24 10:31
閱讀 3875·2021-09-22 15:16
閱讀 3395·2021-09-22 10:02
閱讀 1010·2021-09-22 10:02
閱讀 1822·2021-09-08 09:36
閱讀 1974·2019-08-30 14:18
閱讀 609·2019-08-30 10:51
閱讀 1863·2019-08-29 11:08