基于JavaScript作用域鏈的性能調(diào)優(yōu)

JavaScript作用域和作用域鏈捺僻,說起來很簡單涨椒,但是細細分析,大有玄機黄选。只能真正理解了作用域鏈原理伏伯,才能寫出更高效的JavaScript代碼橘洞。下面,讓我們慢慢走近這個并不神秘的區(qū)域......

1. 作用域和執(zhí)行上下文

參考:深入理解JavaScript作用域和作用域鏈 - 感謝@qwelz訂正

JavaScript 的執(zhí)行分為:解釋和執(zhí)行兩個階段,這兩個階段所做的事并不一樣:

  • 解釋階段:
    • 詞法分析
    • 語法分析
    • 作用域規(guī)則確定
  • 執(zhí)行階段:
    • 創(chuàng)建執(zhí)行上下文
    • 執(zhí)行函數(shù)代碼
    • 垃圾回收

JavaScript 解釋階段便會確定作用域規(guī)則舵鳞,因此作用域在函數(shù)定義時就已經(jīng)確定了震檩,而不是在函數(shù)調(diào)用時確定,但是執(zhí)行上下文是函數(shù)執(zhí)行之前創(chuàng)建的。執(zhí)行上下文最明顯的就是 this 的指向是執(zhí)行時確定的抛虏。而作用域訪問的變量是編寫代碼的結構確定的博其。

作用域和執(zhí)行上下文之間最大的區(qū)別是:
執(zhí)行上下文在運行時確定,隨時可能改變迂猴;作用域在定義時就確定慕淡,并且不會改變。

2. 執(zhí)行上下文

執(zhí)行JavaScript代碼時沸毁,JavaScript引擎會創(chuàng)建一個執(zhí)行上下文峰髓,它設定了代碼執(zhí)行時所處的環(huán)境。

下面一步步剖析~

當頁面加載完畢后(含有需要執(zhí)行的JavaScript代碼)息尺,JavaScript引擎會做哪些事情携兵?

  1. 創(chuàng)建一個全局的執(zhí)行上下文(this指向我們熟知的window);
  2. 每執(zhí)行一個JavaScript函數(shù)搂誉,都會創(chuàng)建一個對應的執(zhí)行上下文徐紧;
  3. 函數(shù)里面可能執(zhí)行嵌套函數(shù)......繼續(xù)創(chuàng)建子函數(shù)的執(zhí)行上下文;
  4. 最終炭懊,會創(chuàng)建出一個棧并级,當前作用域在棧頂,全局作用域在棧底侮腹;

棧頂?shù)暮瘮?shù)會最先運行嘲碧,運行完畢后出棧,繼續(xù)運行一下個函數(shù)......直到棧清空父阻。

3. 作用域鏈

每個執(zhí)行上下文都有一個與之關聯(lián)的作用域鏈愈涩。

當函數(shù)被創(chuàng)建時(注意,不是執(zhí)行)至非,JavaScript引擎會把創(chuàng)建時執(zhí)行上下文的作用域鏈賦給函數(shù)內(nèi)部屬性[Scope]钠署。
然后糠聪,函數(shù)被執(zhí)行荒椭,JavaScript引擎創(chuàng)建一個活動對象(Active object),添加到作用域鏈頂部舰蟆。

用一個例子做進一步說明:

function add(num1, num2){
  var sum = num1 + num2;
  return sum;
}

var total = add(5, 10);

(圖例來自網(wǎng)絡)


scope chain.jpg

執(zhí)行上面的JavaScript代碼趣惠,但還沒有執(zhí)行add函數(shù)時,add函數(shù)scope chain只有一個值身害,指向global object味悄。
然后,執(zhí)行add函數(shù)塌鸯,一個活動對象被創(chuàng)建侍瑟,并且被加到scope chain頂部。
由此,執(zhí)行add函數(shù)時涨颜,一個兩層的作用域鏈被建立费韭。

小貼士

無論是全局對象還是活動對象,都會在初始化時給this, arguments賦值庭瑰;
也會給局部變量星持,局部參數(shù)賦值。

顯而易見弹灭,add函數(shù)被執(zhí)行時督暂,需要尋找num1和num2的值做計算。
如果在頂層作用域找不到這兩個值穷吮,那么逻翁,JavaScript引擎會沿著作用域鏈,在下一層活動對象/全局對象中查找......找到即返回捡鱼,找不到繼續(xù)往下......直到全局對象window卢未。

4. 性能優(yōu)化:盡可能使用局部變量

通過上面的分析,可以得出結論堰汉,如果在越靠近棧頂?shù)膶ο笾辛缮纾梢哉业疆斍昂瘮?shù)執(zhí)行時所需的變量,那么翘鸭,函數(shù)執(zhí)行速度是最快的滴铅。

也就是說,讀取變量值的總耗時隨著查找作用域鏈的逐層深入而不斷增加就乓!

因此汉匙,為了寫出更高效的JavaScript代碼,盡可能在函數(shù)內(nèi)部使用局部變量生蚁。比如下面的寫法就不好:

function createChild(elemID) {
  var element = document.getElementById(elemID); // 在global對象中查找document
  var newElem = document.createElement('div');  // 在global對象中查找document
  element.appendChild(newElem);  //總計查找兩次
}

應該改為:

function createChild(elemID) {
  var doc = document; // 在global對象中查找document
  var element = doc.getElementById(elemID);
  var newElem = doc.createElement('div');
  element.appendChild(newElem); //總計查找一次
}

小結

可見噩翠,要想寫出高性能的JavaScript代碼并不難,一點小修改也有大作為~

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末邦投,一起剝皮案震驚了整個濱河市伤锚,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌志衣,老刑警劉巖屯援,帶你破解...
    沈念sama閱讀 221,576評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異念脯,居然都是意外死亡狞洋,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,515評論 3 399
  • 文/潘曉璐 我一進店門绿店,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吉懊,“玉大人,你說我怎么就攤上這事〗杷裕” “怎么了怕午?”我有些...
    開封第一講書人閱讀 168,017評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長淹魄。 經(jīng)常有香客問我郁惜,道長,這世上最難降的妖魔是什么甲锡? 我笑而不...
    開封第一講書人閱讀 59,626評論 1 296
  • 正文 為了忘掉前任兆蕉,我火速辦了婚禮,結果婚禮上缤沦,老公的妹妹穿的比我還像新娘虎韵。我一直安慰自己,他們只是感情好缸废,可當我...
    茶點故事閱讀 68,625評論 6 397
  • 文/花漫 我一把揭開白布包蓝。 她就那樣靜靜地躺著,像睡著了一般企量。 火紅的嫁衣襯著肌膚如雪测萎。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,255評論 1 308
  • 那天届巩,我揣著相機與錄音硅瞧,去河邊找鬼。 笑死恕汇,一個胖子當著我的面吹牛腕唧,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播瘾英,決...
    沈念sama閱讀 40,825評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼枣接,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了缺谴?” 一聲冷哼從身側響起但惶,我...
    開封第一講書人閱讀 39,729評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎瓣赂,沒想到半個月后榆骚,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體片拍,經(jīng)...
    沈念sama閱讀 46,271評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡煌集,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,363評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了捌省。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片苫纤。...
    茶點故事閱讀 40,498評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出卷拘,到底是詐尸還是另有隱情喊废,我是刑警寧澤,帶...
    沈念sama閱讀 36,183評論 5 350
  • 正文 年R本政府宣布栗弟,位于F島的核電站污筷,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏乍赫。R本人自食惡果不足惜瓣蛀,卻給世界環(huán)境...
    茶點故事閱讀 41,867評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望雷厂。 院中可真熱鬧惋增,春花似錦、人聲如沸改鲫。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,338評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽像棘。三九已至稽亏,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間缕题,已是汗流浹背措左。 一陣腳步聲響...
    開封第一講書人閱讀 33,458評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留避除,地道東北人怎披。 一個月前我還...
    沈念sama閱讀 48,906評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像瓶摆,于是被迫代替她去往敵國和親凉逛。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 45,507評論 2 359

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