詞法作用域(欺騙詞法eval & with)

一何恶、概念

1捌议、詞法作用域就是定義在詞法階段的作用域哼拔。換句話說,詞法作用域是由你在寫代碼時將變量和塊作用域?qū)懺谀睦飦頉Q定的瓣颅。是一套關(guān)于引擎如何尋找變量以及會在何處找到變量的規(guī)則倦逐。
2、遮蔽效應(yīng):在多層的嵌套作用域中可以定義同名的
標(biāo)識符宫补,即內(nèi)部的標(biāo)識符“遮蔽”了外部的標(biāo)識符
3檬姥、動態(tài)作用域:在運行時確定的,關(guān)注函數(shù)從何處調(diào)用(js沒有動態(tài)作用域)粉怕。(詞法作用域是寫代碼或者說定義時確定的健民,關(guān)注函數(shù)在何處聲明)

二、查找

1贫贝、作用域查找始終從運行時所處的最內(nèi)部作用域開始秉犹,逐級向外或者說向上進(jìn)行蛉谜,直到遇見第一個匹配的標(biāo)識符為止。
2崇堵、全局變量會自動成為全局對象(比如瀏覽器中的 window 對象)的屬性型诚,因此可以不直接通過全局對象的詞法名稱,而是間接地通過對全局對象屬性的引用來對其進(jìn)行訪問鸳劳。如 window.a 狰贯,通過這種技術(shù)可以訪問那些被同名變量所遮蔽的全局變量。但非全局的變量如果被遮蔽了赏廓,無論如何都無法被訪問到暮现。

三、欺騙詞法

1楚昭、:欺騙詞法作用域會導(dǎo)致性能下降栖袋。

2、實現(xiàn)欺騙詞法的兩種機(jī)制:
①抚太、eval(..):對一段包含一個或多個聲明的“代碼”字符串進(jìn)行演算塘幅,并借此來修改已經(jīng)存在的詞法作用域(在運行時)

function foo(str, a) {
  eval( str ); // 欺騙!相當(dāng)于 var b = 3;
  console.log( a, b );
}
var b = 2;
foo( "var b = 3;", 1 ); // 1, 3
  • eval(..) 調(diào)用中的 "var b = 3;" 這段代碼會被當(dāng)作本來就在那里一樣來處理
  • 這段代碼實際上在 foo(..) 內(nèi)部創(chuàng)建了一個變量 b尿贫,并遮蔽
    了外部(全局)作用域中的同名變量电媳。 console.log(..) 被執(zhí)行時,會在 foo(..) 的內(nèi)部同時找到 a 和 b庆亡,但是永遠(yuǎn)也無法找到外部的 b匾乓。因此會輸出“1, 3”
  • 實際上,eval(..) 通常被用來執(zhí)行動態(tài)創(chuàng)建的代碼
  • 嚴(yán)格模式下,eval(..) 在運行時有其自己的詞法作用域又谋,意味著其中的聲明無法修改所在的作用域
function foo(str) {
   "use strict";
   eval( str );
   console.log( a ); // ReferenceError: a is not defined
 }
 foo( "var a = 2" );

②拼缝、with:本質(zhì)上是通過將一個對象的引用當(dāng)作作用域來處理,將對象的屬性當(dāng)作作用域中的標(biāo)識符來處理彰亥,從而創(chuàng)建了一個新的詞法作用域(同樣是在運行時)咧七。

  • with 通常被當(dāng)作重復(fù)引用同一個對象中的多個屬性的快捷方式,可以不需要重復(fù)引用對象本身
var obj = {
 a: 1,
 b: 2,
 c: 3
};
// 單調(diào)乏味的重復(fù) "obj"
obj.a = 2;
obj.b = 3;
obj.c = 4;
// 簡單的快捷方式
with (obj) {
 a = 3;
 b = 4;
 c = 5;
}
  • 盡管 with 塊可以將一個對象處理為詞法作用域任斋,但是這個塊內(nèi)部正常的 var聲明并不會被限制在這個塊的作用域中继阻,而是被添加到 with 所處的函數(shù)作用域中

注:理解下面這個例子:

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 被泄漏到全局作用域上了瘟檩!
  • 當(dāng)我們傳遞 o1 給 with 時,with 所聲明的作用域是 o1澈蟆,而這個作用域中含有一個同 o1.a 屬性相符的標(biāo)識符墨辛。
  • 但當(dāng)我們將 o2 作為作用域時,其中并沒有 a 標(biāo)識符丰介,因此進(jìn)行了正常的 LHS 標(biāo)識符查找背蟆。 o2 的作用域、foo(..) 的作用域和全局作用域中都沒有找到標(biāo)識符 a哮幢,因此當(dāng) a=2 執(zhí)行時带膀,自動創(chuàng)建了一個全局變量(因為是非嚴(yán)格模式)

三、性能

JavaScript 引擎會在編譯階段進(jìn)行數(shù)項的性能優(yōu)化橙垢。其中有些優(yōu)化依賴于能夠根據(jù)代碼的詞法進(jìn)行靜態(tài)分析垛叨,并預(yù)先確定所有變量和函數(shù)的定義位置,才能在執(zhí)行過程中快速找到標(biāo)識符柜某。

如果引擎在代碼中發(fā)現(xiàn)了 eval(..) 或 with嗽元,無法在詞法分析階段明確知道 eval(..) 會接收到什么代碼,這些代碼會如何對作用域進(jìn)行修改喂击,也無法知道傳遞給 with 用來創(chuàng)建新詞法作用域的對象的內(nèi)容到底是什么剂癌。

引擎無法在編譯時對作用域查找進(jìn)行優(yōu)化,因為引擎只能謹(jǐn)慎地認(rèn)為這樣的優(yōu)化是無效的翰绊。使用這其中任何一個機(jī)制都將導(dǎo)致代碼運行變慢佩谷。

最悲觀的情況是如果出現(xiàn)了 eval(..) 或 with,所有的優(yōu)化可能都是無意義的监嗜,因此最簡單的做法就是完全不做任何優(yōu)化谐檀。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市裁奇,隨后出現(xiàn)的幾起案子桐猬,更是在濱河造成了極大的恐慌,老刑警劉巖刽肠,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件溃肪,死亡現(xiàn)場離奇詭異,居然都是意外死亡音五,警方通過查閱死者的電腦和手機(jī)乍惊,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來放仗,“玉大人润绎,你說我怎么就攤上這事〉ぃ” “怎么了莉撇?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長惶傻。 經(jīng)常有香客問我棍郎,道長,這世上最難降的妖魔是什么银室? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任涂佃,我火速辦了婚禮励翼,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘辜荠。我一直安慰自己汽抚,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布伯病。 她就那樣靜靜地躺著造烁,像睡著了一般。 火紅的嫁衣襯著肌膚如雪午笛。 梳的紋絲不亂的頭發(fā)上惭蟋,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天,我揣著相機(jī)與錄音药磺,去河邊找鬼告组。 笑死,一個胖子當(dāng)著我的面吹牛癌佩,可吹牛的內(nèi)容都是我干的惹谐。 我是一名探鬼主播,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼驼卖,長吁一口氣:“原來是場噩夢啊……” “哼氨肌!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起酌畜,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤怎囚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后桥胞,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體恳守,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年贩虾,在試婚紗的時候發(fā)現(xiàn)自己被綠了催烘。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡缎罢,死狀恐怖伊群,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情策精,我是刑警寧澤舰始,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布,位于F島的核電站咽袜,受9級特大地震影響丸卷,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜询刹,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一谜嫉、第九天 我趴在偏房一處隱蔽的房頂上張望萎坷。 院中可真熱鬧,春花似錦沐兰、人聲如沸哆档。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至象泵,卻和暖如春寞秃,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背偶惠。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工春寿, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人忽孽。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓绑改,卻偏偏與公主長得像,于是被迫代替她去往敵國和親兄一。 傳聞我的和親對象是個殘疾皇子厘线,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容

  • 在上一篇文章中,小編介紹了詞法作用域出革,并在其中提到了兩個會出現(xiàn)“欺騙”詞法作用域的關(guān)鍵字——eval和with造壮,今...
    技術(shù)小王閱讀 222評論 0 0
  • 一.欺騙詞法作用域 1.eval ①eval函數(shù)可以接收一個字符串作為參數(shù),以動態(tài)形式插入程序的某個位置骂束,并對其詞...
    姚屹晨閱讀 1,403評論 0 2
  • 我們活著的每一刻背后都隱藏著成千上萬個不一樣的瞬間耳璧。 ——《忽然七日》 大部分情況下,詞法作用域在編譯階段的第...
    BIGHAI閱讀 287評論 0 1
  • 官方中文版原文鏈接 感謝社區(qū)中各位的大力支持展箱,譯者再次奉上一點點福利:阿里云產(chǎn)品券旨枯,享受所有官網(wǎng)優(yōu)惠,并抽取幸運大...
    HetfieldJoe閱讀 2,394評論 0 11
  • 在之前我們講過混驰,將作用域定義成“一套規(guī)則”攀隔,這套規(guī)則用于管理引擎如何在當(dāng)前作用域以及嵌套的子作用域中根據(jù)標(biāo)識符名稱...
    我就是z閱讀 1,044評論 4 9