JavaScript運(yùn)行原理

概念

  • Execute Context:執(zhí)行上下文
  • Execute Context Stack:執(zhí)行上下文棧(或 Call Stack 調(diào)用棧)脑题,存儲代碼運(yùn)行期間創(chuàng)建的所以上下文
  • Event Loop:引擎運(yùn)行 js 線程的方式
  • 引擎:從頭到尾負(fù)責(zé)整個 JavaScript 程序的編譯及執(zhí)行過程
  • 編譯器:負(fù)責(zé)語法分析及代碼生成等
  • 作用域:負(fù)責(zé)收集并維護(hù)由所有聲明的標(biāo)識符(變量)組成的一系列查詢菩暗,并實(shí)施一套非常嚴(yán)格的規(guī)則,確定當(dāng)前執(zhí)行的代碼對這些標(biāo)識符的訪問權(quán)限

JavaScript 的運(yùn)行分為兩部分:編譯旭蠕、執(zhí)行

一些問題

  • 為什么使用棧結(jié)構(gòu)存儲運(yùn)行時的執(zhí)行上下文?
    function second() {
      console.log(name);
    }
    
    function first() {
      var name = '2';
      second();
    }
    
    var name = '1';
    first();
    // 輸出:1
    
  • 進(jìn)程與線程
    進(jìn)程:資源分配的最小單位;進(jìn)程擁有獨(dú)立的堆椞桶荆空間數(shù)據(jù)段佑稠,每當(dāng)啟動一個新的進(jìn)程必須分配給它獨(dú)立的地址空間,建立眾多的數(shù)據(jù)表來維護(hù)它的代碼段旗芬、堆棧段數(shù)據(jù)段
    線程:程序執(zhí)行的最小單位舌胶;線程擁有獨(dú)立的堆棧空間疮丛,但是共享數(shù)據(jù)段幔嫂,它們彼此之間使用相同的地址空間,共享大部分?jǐn)?shù)據(jù)誊薄,比進(jìn)程更節(jié)儉履恩,開銷比較小,切換速度也比進(jìn)程快呢蔫,效率高

JavaScript 的執(zhí)行分為兩個階段:1. 創(chuàng)建執(zhí)行上下文切心;2. 執(zhí)行代碼;

執(zhí)行上下文

執(zhí)行上下文有三種類型:全局執(zhí)行上下文片吊、函數(shù)執(zhí)行上下文绽昏、Eval 函數(shù)執(zhí)行上下文

執(zhí)行上下文的數(shù)據(jù)結(jié)構(gòu):

// ES3 例:
function foo(i) {
    var a = 'hello';
    var b = function bar() {

    };
    function c() {

    }
}

foo(22);

創(chuàng)建階段

fooExecutionContext = {
    scopeChain: { ... },
    variableObject: {
        arguments: {
            0: 22,
            length: 1
        },
        i: 22,
        c: pointer to function c()
        a: undefined,
        b: undefined
    },
    this: { ... }
}

ES3 的函數(shù)執(zhí)行上下文包括:

  • scopeChain:指向上一個作用域(新概念)
  • variableObject:包含函數(shù)的參數(shù) arguments 和函數(shù)內(nèi)聲明的變量
  • this:執(zhí)行函數(shù)的調(diào)用者

在創(chuàng)建階段函數(shù)內(nèi)聲明的變量都初始化為 undefined,在執(zhí)行階段將在棧中存儲(數(shù)據(jù)段俏脊?)或堆中存儲的值賦給變量(說明有一個收集值的過程全谤,但在創(chuàng)建階段為什么就初始化了參數(shù)的值?)
函數(shù)每調(diào)用一次爷贫,都會產(chǎn)生一個新的執(zhí)行上下文環(huán)境认然。因此不同的調(diào)用可能就有不同的參數(shù)。

總結(jié):ES3 的執(zhí)行上下文
創(chuàng)建階段:1. 創(chuàng)建作用域鏈沸久;2. 創(chuàng)建變量對象VO(包括參數(shù)季眷,函數(shù),變量)卷胯;3. 確定this的值
激活/執(zhí)行階段:完成變量分配子刮,執(zhí)行代碼

ES5 的執(zhí)行上下文


FunctionExectionContext = {  
   
  this: <Global Object>,

  LexicalEnvironment: {  
    EnvironmentRecord: {  
      Type: "Declarative",  // 環(huán)境記錄分類: 聲明環(huán)境記錄
      Arguments: {0: 20, 1: 30, length: 2},  // 函數(shù)環(huán)境下,環(huán)境記錄比全局環(huán)境下的環(huán)境記錄多了argument對象
    },  
    outer: <GlobalLexicalEnvironment>  
  },

  VariableEnvironment: {  
    EnvironmentRecord: {  
      Type: "Declarative",  // 環(huán)境記錄分類: 聲明環(huán)境記錄
      g: undefined  
    },  
    outer: <GlobalLexicalEnvironment>  
  }  
}

一些問題

  • 詞法作用域意味著作用域是由書寫代碼時函數(shù)聲明的位置來決定的窑睁。編譯的詞法分析階段基本能夠知道全部標(biāo)識符在哪里以及時如何聲明的挺峡,從而能夠預(yù)測在執(zhí)行過程中如何對它們進(jìn)行查找(找到所有的聲明,并用適合的左右域?qū)⑺鼈冴P(guān)聯(lián)起來)

// 包括變量和函數(shù)在內(nèi)的所有聲明都會在任何代碼被執(zhí)行之前首先被處理(變量提升)
// 函數(shù)優(yōu)先

foo()
var foo;
function foo() {
  console.log('1');
}
foo = function() {
  console.log('2')
}
// 這段代碼會被*引擎*理解為如下形式
function foo() { // 變量提升 函數(shù)優(yōu)先
  console.log('1')
}
// var foo = undefined 重復(fù)的變量聲明 被忽略
foo(); // 1
foo = function() {
  console.log('2');
}

在傳統(tǒng)編譯語言的流程中担钮,程序的一段源代碼執(zhí)行之前會經(jīng)歷三個步驟橱赠,統(tǒng)稱為”編譯“

  • 詞法分析:將代碼的字符串分解成詞法單元(token)
  • 語法分析:將詞法單元流(數(shù)組)轉(zhuǎn)換成抽象語法樹 AST
  • 代碼生成:將 AST 轉(zhuǎn)換成可執(zhí)行代碼

任何 JavaScript 代碼片段在執(zhí)行前都要進(jìn)行編譯(通常就在執(zhí)行前)

  • var 重復(fù)聲明變量會被忽略、不允許使用let const重復(fù)聲明變量箫津,function 重復(fù)聲明的變量后面會覆蓋前面

作用域:全局作用域狭姨、函數(shù)作用域宰啦、塊作用域({} 創(chuàng)建,不是 object)

let饼拍、const 將變量綁定塊級作用域
let赡模、const 的暫時死區(qū):

console.log(a);  // undefined (變量提升)
console.log(b);  // ReferenceError: Cannot access 'b' before initialization (暫時死區(qū))
var a = 1;
const b = 2;

塊作用域里的函數(shù)聲明

foo(); // b
var a = true;
if(a) {
  function foo() {console.log('a')}
} else {
  function foo() {console.log('b')}
}

作用域和執(zhí)行上下文的區(qū)別

  • 作用域:函數(shù)聲明時確定
  • 執(zhí)行上下文:函數(shù)每調(diào)用一次,都會產(chǎn)生一個新的執(zhí)行上下文環(huán)境师抄,處于活動狀態(tài)的執(zhí)行上下文環(huán)境只有一個漓柑。(在你不知道的JavaScript這本書中,執(zhí)行上下文被叫做動態(tài)作用域)

    變量叨吮、函數(shù)表達(dá)式——變量聲明(默認(rèn)賦值為undefined)
    this——賦值辆布;
    函數(shù)聲明——賦值;

this

this 屬于執(zhí)行上下文的一個屬性茶鉴;由于每次調(diào)用函數(shù)都會生成一個新的執(zhí)行上下文锋玲,所以每次調(diào)用函數(shù)都會給 this 賦值;this 表示函數(shù)被誰調(diào)用

箭頭函數(shù)

用當(dāng)前的詞法作用域覆蓋了 this 本來的值蛤铜;this 的值同當(dāng)前詞法作用域?qū)?yīng)的執(zhí)行上下文的 this 的值嫩絮;

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市围肥,隨后出現(xiàn)的幾起案子剿干,更是在濱河造成了極大的恐慌,老刑警劉巖穆刻,帶你破解...
    沈念sama閱讀 221,198評論 6 514
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件置尔,死亡現(xiàn)場離奇詭異,居然都是意外死亡氢伟,警方通過查閱死者的電腦和手機(jī)榜轿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,334評論 3 398
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朵锣,“玉大人谬盐,你說我怎么就攤上這事〕闲” “怎么了飞傀?”我有些...
    開封第一講書人閱讀 167,643評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長诬烹。 經(jīng)常有香客問我砸烦,道長,這世上最難降的妖魔是什么绞吁? 我笑而不...
    開封第一講書人閱讀 59,495評論 1 296
  • 正文 為了忘掉前任幢痘,我火速辦了婚禮,結(jié)果婚禮上家破,老公的妹妹穿的比我還像新娘颜说。我一直安慰自己购岗,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,502評論 6 397
  • 文/花漫 我一把揭開白布门粪。 她就那樣靜靜地躺著藕畔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪庄拇。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,156評論 1 308
  • 那天韭邓,我揣著相機(jī)與錄音措近,去河邊找鬼。 笑死女淑,一個胖子當(dāng)著我的面吹牛瞭郑,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鸭你,決...
    沈念sama閱讀 40,743評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼屈张,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了袱巨?” 一聲冷哼從身側(cè)響起阁谆,我...
    開封第一講書人閱讀 39,659評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎愉老,沒想到半個月后场绿,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,200評論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡嫉入,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,282評論 3 340
  • 正文 我和宋清朗相戀三年焰盗,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片咒林。...
    茶點(diǎn)故事閱讀 40,424評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡熬拒,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出垫竞,到底是詐尸還是另有隱情澎粟,我是刑警寧澤,帶...
    沈念sama閱讀 36,107評論 5 349
  • 正文 年R本政府宣布件甥,位于F島的核電站捌议,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏引有。R本人自食惡果不足惜瓣颅,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,789評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望譬正。 院中可真熱鬧宫补,春花似錦檬姥、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,264評論 0 23
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至贫贝,卻和暖如春秉犹,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背稚晚。 一陣腳步聲響...
    開封第一講書人閱讀 33,390評論 1 271
  • 我被黑心中介騙來泰國打工崇堵, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人客燕。 一個月前我還...
    沈念sama閱讀 48,798評論 3 376
  • 正文 我出身青樓鸳劳,卻偏偏與公主長得像,于是被迫代替她去往敵國和親也搓。 傳聞我的和親對象是個殘疾皇子赏廓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,435評論 2 359

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

  • 今天感恩節(jié)哎,感謝一直在我身邊的親朋好友傍妒。感恩相遇幔摸!感恩不離不棄。 中午開了第一次的黨會拍顷,身份的轉(zhuǎn)變要...
    迷月閃星情閱讀 10,567評論 0 11
  • 彩排完抚太,天已黑
    劉凱書法閱讀 4,220評論 1 3
  • 表情是什么,我認(rèn)為表情就是表現(xiàn)出來的情緒昔案。表情可以傳達(dá)很多信息尿贫。高興了當(dāng)然就笑了,難過就哭了踏揣。兩者是相互影響密不可...
    Persistenc_6aea閱讀 125,276評論 2 7