詞法作用域

我們知道JavaScript并不具有動(dòng)態(tài)作用域,它只有詞法作用域,什么是詞法作用域墓阀?

一、 詞法作用域

詞法作用域就是定義在詞法階段的作用域拓轻。換句話說斯撮,詞法作用域是由你在寫代碼時(shí)將變量和塊作用域?qū)懺谀睦飦頉Q定的。
無論函數(shù)在哪里被調(diào)用扶叉,也無論它如何被調(diào)用勿锅,它的詞法作用域都只由函數(shù)被聲明時(shí)所處的位置決定。

var value = 1;
function foo() {
    console.log(value);
}
function bar() {
    var value = 2;
    foo();
}
bar();
// 結(jié)果是 ???

假設(shè)JavaScript采用靜態(tài)作用域枣氧,讓我們分析下執(zhí)行過程:
執(zhí)行 foo 函數(shù)溢十,先從 foo 函數(shù)內(nèi)部查找是否有局部變量 value,如果沒有达吞,就根據(jù)書寫的位置张弛,查找上面一層的代碼,也就是 value 等于 1酪劫,所以結(jié)果會(huì)打印 1吞鸭。
假設(shè)JavaScript采用動(dòng)態(tài)作用域,讓我們分析下執(zhí)行過程:
執(zhí)行 foo 函數(shù)覆糟,依然是從 foo 函數(shù)內(nèi)部查找是否有局部變量 value刻剥。如果沒有,就從調(diào)用函數(shù)的作用域滩字,也就是 bar 函數(shù)內(nèi)部查找 value 變量造虏,所以結(jié)果會(huì)打印 2盯滚。

前面我們已經(jīng)說了,JavaScript采用的是詞法作用域酗电,所以這個(gè)例子的結(jié)果是 1魄藕。

二、 but撵术,eval()和with可以通過其特殊性用來“欺騙”詞法作用域

欺騙詞法

JavaScript 中有兩種機(jī)制來實(shí)現(xiàn):在運(yùn)行時(shí)來“修 改”(也可以說欺騙)詞法作用域背率,欺騙詞法作用域會(huì)導(dǎo)致性能下降,所以不要使用eval和with嫩与。
(1)eval()
eval() 函數(shù)可以接受一個(gè)字符串為參數(shù)寝姿,對(duì)一段包含一個(gè)或多個(gè)聲明的“代碼”字符串進(jìn)行演算,并借此來修改已經(jīng)存在的詞法作用域(在運(yùn)行時(shí))划滋;

  function foo(str, a) {
    eval( str ); // 欺騙饵筑!
    console.log( a, b );
}
var b = 2;
foo( "var b = 3;", 1 ); // 1, 3

// 上面代碼中,eval()調(diào)用中的"var b = 3;"這段代碼會(huì)被當(dāng)作本來就在那里一樣來處理处坪。
// 由于那段代 碼聲明了一個(gè)新的變量b根资,因此它對(duì)已經(jīng)存在的foo()的詞法作用域進(jìn)行了修改。
// 這段代碼實(shí)際上在 foo() 內(nèi)部創(chuàng)建了一個(gè)變量 b同窘,并遮蔽 了外部(全局)作用域中的同名變量玄帕。

但在嚴(yán)格模式的程序中,eval()在運(yùn)行時(shí)有其自己的詞法作用域想邦,意味著其中的聲明無法修改所在的作用域裤纹。

  function foo(str) {
    "use strict";
    eval( str );
    console.log( a ); // ReferenceError: a is not defined
}
foo( "var a = 2" );

(2)with
with 通常被當(dāng)作重復(fù)引用同一個(gè)對(duì)象中的多個(gè)屬性的快捷方式,可以不需要重復(fù)引用對(duì)象本身丧没。
with 通過將一個(gè)對(duì)象的引用當(dāng)作作用域來處理鹰椒,將對(duì)象的屬性當(dāng)作作用域中的標(biāo)識(shí)符來處理,從而創(chuàng)建了一個(gè)新的詞法作用域(在運(yùn)行時(shí))呕童。
盡管with 塊可以將一個(gè)對(duì)象處理為詞法作用域漆际,但是這個(gè)塊內(nèi)部正常的var聲明并不會(huì)被限制在這個(gè)塊的作用域中,而是被添加到with 所處的函數(shù)作用域中拉庵。

function foo(obj) {
    with (obj) {
        a = 2;
    }
}
var o1 = {a: 3};
var o2 = {b: 3};

// 將 o1 傳遞進(jìn)去灿椅,a=2 賦值操作找到了 o1.a 并將 2 賦值給它
foo( o1 );
console.log( o1.a ); // 2

// 當(dāng) o2 傳遞進(jìn)去,o2 并沒有 a 屬性钞支,因此不會(huì)創(chuàng)建這個(gè)屬性茫蛹, o2.a 保持 undefined
// 此時(shí),a = 2 賦值操作創(chuàng)建了一個(gè)全局的變量 a
foo( o2 );
console.log( o2.a ); // undefined
console.log( a ); // 2——不好烁挟,a 被泄漏到全局作用域上了婴洼!

eval() 函數(shù)如果接受了含有一個(gè)或多個(gè)聲明的代碼,就會(huì)修改其所處的詞法作用域撼嗓;

with 聲明實(shí)際上是根據(jù)你傳遞給它的對(duì)象憑空創(chuàng)建了一個(gè)全新的詞法作用域柬采。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末欢唾,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子粉捻,更是在濱河造成了極大的恐慌礁遣,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,525評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肩刃,死亡現(xiàn)場(chǎng)離奇詭異祟霍,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)盈包,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,203評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門沸呐,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人呢燥,你說我怎么就攤上這事崭添。” “怎么了叛氨?”我有些...
    開封第一講書人閱讀 164,862評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵呼渣,是天一觀的道長(zhǎng)。 經(jīng)常有香客問我力试,道長(zhǎng)徙邻,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,728評(píng)論 1 294
  • 正文 為了忘掉前任畸裳,我火速辦了婚禮,結(jié)果婚禮上淳地,老公的妹妹穿的比我還像新娘怖糊。我一直安慰自己,他們只是感情好颇象,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,743評(píng)論 6 392
  • 文/花漫 我一把揭開白布伍伤。 她就那樣靜靜地躺著,像睡著了一般遣钳。 火紅的嫁衣襯著肌膚如雪扰魂。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,590評(píng)論 1 305
  • 那天蕴茴,我揣著相機(jī)與錄音劝评,去河邊找鬼。 笑死倦淀,一個(gè)胖子當(dāng)著我的面吹牛蒋畜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播撞叽,決...
    沈念sama閱讀 40,330評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼姻成,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼插龄!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起科展,我...
    開封第一講書人閱讀 39,244評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤均牢,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后才睹,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體膨处,經(jīng)...
    沈念sama閱讀 45,693評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,885評(píng)論 3 336
  • 正文 我和宋清朗相戀三年砂竖,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了真椿。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,001評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡乎澄,死狀恐怖突硝,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情置济,我是刑警寧澤解恰,帶...
    沈念sama閱讀 35,723評(píng)論 5 346
  • 正文 年R本政府宣布,位于F島的核電站浙于,受9級(jí)特大地震影響护盈,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜羞酗,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,343評(píng)論 3 330
  • 文/蒙蒙 一腐宋、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧檀轨,春花似錦胸竞、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,919評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至讹挎,卻和暖如春校赤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背筒溃。 一陣腳步聲響...
    開封第一講書人閱讀 33,042評(píng)論 1 270
  • 我被黑心中介騙來泰國(guó)打工马篮, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人铡羡。 一個(gè)月前我還...
    沈念sama閱讀 48,191評(píng)論 3 370
  • 正文 我出身青樓积蔚,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親烦周。 傳聞我的和親對(duì)象是個(gè)殘疾皇子尽爆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,955評(píng)論 2 355