成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專(zhuān)欄INFORMATION COLUMN

javascript系列--javascript引擎執(zhí)行的過(guò)程的理解--語(yǔ)法分析和預(yù)編譯階段

malakashi / 3103人閱讀

摘要:所以覺(jué)得把這個(gè)執(zhí)行的詳細(xì)過(guò)程整理一下,幫助更好的理解。類(lèi)似的語(yǔ)法報(bào)錯(cuò)的如下圖所示三預(yù)編譯階段代碼塊通過(guò)語(yǔ)法分析階段之后,語(yǔ)法都正確的下回進(jìn)入預(yù)編譯階段。另開(kāi)出新文章詳細(xì)分析,主要介紹執(zhí)行階段中的同步任務(wù)執(zhí)行和異步任務(wù)執(zhí)行機(jī)制事件循環(huán)。

一、概述

js是一種非常靈活的語(yǔ)言,理解js引擎的執(zhí)行過(guò)程對(duì)于我們學(xué)習(xí)js是非常有必要的??戳撕芏噙@方便文章,大多數(shù)是講的是事件循環(huán)(event loop)或者變量提升的等,并沒(méi)有全面分析其中的過(guò)程。所以覺(jué)得把這個(gè)js執(zhí)行的詳細(xì)過(guò)程整理一下,幫助更好的理解js。

1.1基礎(chǔ)概念

js是單線程語(yǔ)言。

在瀏覽器中一個(gè)頁(yè)面永遠(yuǎn)只有一個(gè)線程在執(zhí)行js腳本代碼

js是單線程怨言,但是代碼解析是非常迅速的,不會(huì)發(fā)生解析阻塞。

js是異步執(zhí)行的,通過(guò)實(shí)踐循環(huán)(event loop)方式實(shí)現(xiàn)的

暫時(shí)我們不考慮事件循環(huán)(event loop),我們先來(lái)看這樣一段代碼,來(lái)確定我們是否理解js引擎的執(zhí)行過(guò)程

console.log(person)

console.log(personFun)

var person = "saucxs";

console.log(person)

function personFun() {
    console.log(person)
    var person = "songEagle";
    console.log(person)
}

personFun()

console.log(person)

可以自己直接使用瀏覽器看出輸出結(jié)果

首先我們來(lái)分析一下上面的代碼,雖然很多開(kāi)發(fā)人員基本上都能答出來(lái),但是還是要啰嗦一下。

全面分析js引擎的執(zhí)行過(guò)程,分為三個(gè)階段

1、語(yǔ)法分析

2、預(yù)編譯階段

3、執(zhí)行階段

說(shuō)明:瀏覽器先按照js的順序加載

三、預(yù)編譯階段

js代碼塊通過(guò)語(yǔ)法分析階段之后,語(yǔ)法都正確的下回進(jìn)入預(yù)編譯階段。

在分析預(yù)編譯階段之前,我們先來(lái)了解一下js的運(yùn)行環(huán)境,運(yùn)行環(huán)境主要由三種:

1、全局環(huán)境(js代碼加載完畢后,進(jìn)入到預(yù)編譯也就是進(jìn)入到全局環(huán)境)

2、函數(shù)環(huán)境(函數(shù)調(diào)用的時(shí)候,進(jìn)入到該函數(shù)環(huán)境,不同的函數(shù),函數(shù)環(huán)境不同)

3、eval環(huán)境(不建議使用,存在安全、性能問(wèn)題)

每進(jìn)入到一個(gè)不同的運(yùn)行環(huán)境都會(huì)創(chuàng)建 一個(gè)相應(yīng)的執(zhí)行上下文(execution context),那么在一段js程序中一般都會(huì)創(chuàng)建多個(gè)執(zhí)行上下文,js引擎會(huì)以棧的數(shù)據(jù)結(jié)構(gòu)對(duì)這些執(zhí)行進(jìn)行處理,形成函數(shù)調(diào)用棧(call stack),棧底永遠(yuǎn)是全局執(zhí)行上下文(global execution context),棧頂則永遠(yuǎn)時(shí)當(dāng)前的執(zhí)行上下文。

3.1函數(shù)調(diào)用棧

什么是函數(shù)調(diào)用棧?

函數(shù)調(diào)用棧就是使用棧存取的方式進(jìn)行管理運(yùn)行環(huán)境,特點(diǎn)是先進(jìn)后出,后進(jìn)后出

我們來(lái)分析一下簡(jiǎn)答的js代碼來(lái)理解函數(shù)調(diào)用棧:

function bar() {
    var B_context = "bar saucxs";

    function foo() {
        var f_context = "foo saucxs";
    }

    foo()
}

bar()

上面代碼塊通過(guò)語(yǔ)法分析后,進(jìn)入預(yù)編譯階段,如圖所示

1、首先進(jìn)入到全局環(huán)境,創(chuàng)建全局執(zhí)行上下文(global Execution Context ),推入到stack中;

2、調(diào)用bar函數(shù),進(jìn)入bar函數(shù)運(yùn)行環(huán)境,創(chuàng)建bar函數(shù)執(zhí)行上下文(bar Execution Context),推入stack棧中;

3、在bar函數(shù)內(nèi)部調(diào)用foo函數(shù),則再進(jìn)入到foo函數(shù)運(yùn)行環(huán)境中,創(chuàng)建foo函數(shù)執(zhí)行上下文(foo Execution Context),如上圖,由于foo函數(shù)內(nèi)部沒(méi)有再調(diào)用其他函數(shù),那么則開(kāi)始出棧;

5、foo函數(shù)執(zhí)行完畢之后,棧頂foo函數(shù)執(zhí)行上下文(foo Execution Context)首先出棧;

6、bar函數(shù)執(zhí)行完畢,bar函數(shù)執(zhí)行上下文(bar Execution Context)出棧;

7、全局上下文(global Execution Cntext)在瀏覽器或者該標(biāo)簽關(guān)閉的時(shí)候出棧。

說(shuō)明:不同的運(yùn)行環(huán)境執(zhí)行都會(huì)進(jìn)入到代碼預(yù)編譯和執(zhí)行兩個(gè)階段,語(yǔ)法分析則在代碼塊加載完畢時(shí)統(tǒng)一檢查語(yǔ)法。

3.2創(chuàng)建執(zhí)行上下文

執(zhí)行上下文可以理解成當(dāng)前的執(zhí)行環(huán)境,與該運(yùn)行環(huán)境相對(duì)應(yīng)。創(chuàng)建執(zhí)行上下文的過(guò)程中,主要是做了下面三件事,如圖所示:

1、創(chuàng)建變量對(duì)象(variable object)

2、創(chuàng)建作用域鏈(scope chain)

3、確定this的指向

3.2.1創(chuàng)建變量對(duì)象

創(chuàng)建變量對(duì)象主要是經(jīng)過(guò)以下過(guò)程,如圖所示:

1、創(chuàng)建arguments對(duì)象,檢查當(dāng)前上下文的參數(shù),建立該對(duì)象的屬性與屬性值,僅在函數(shù)環(huán)境(非箭頭函數(shù))中進(jìn)行的,全局環(huán)境沒(méi)有此過(guò)程。

2、檢查當(dāng)前上下文的函數(shù)聲明,按照代碼順序查找,將找到的函數(shù)提前聲明,如果當(dāng)前上下文的變量對(duì)象沒(méi)有該函數(shù)名屬性,則在該變量對(duì)象以函數(shù)名建立一個(gè)屬性,屬性值則指向該函數(shù)所在堆內(nèi)存地址引用,如果存在,則會(huì)被新的引用覆蓋掉。

3、檢查當(dāng)前上下文的變量聲明,愛(ài)去哪找代碼順序查找,將找到的變量提前聲明,如果當(dāng)前上下文的變量對(duì)象沒(méi)有變量名屬性,則在該變量對(duì)象以變量名建立一個(gè)屬性,屬性值為undefined;如果存在,則忽略該變量聲明。

說(shuō)明:在全局環(huán)境中,window對(duì)象就是全局執(zhí)行上下文的變量對(duì)象,所有的變量和函數(shù)都是window對(duì)象的屬性方法。

所以函數(shù)聲明提前和變量聲明提升是在創(chuàng)建變量對(duì)象中進(jìn)行的,且函數(shù)聲明優(yōu)先級(jí)高于變量聲明。

下面我們?cè)賮?lái)分析這個(gè)簡(jiǎn)單代碼

function fun(m,n){
    var saucxs = 1;

    function execution(){
        console.log(saucxs)
    }
}

fun(2,3)

這里我們?cè)谌汁h(huán)境中調(diào)用fun函數(shù),創(chuàng)建fun的執(zhí)行上下文,這里暫時(shí)不說(shuō)作用域鏈以及this指向的問(wèn)題。

funEC = {
    //變量對(duì)象
    VO: {
        //arguments對(duì)象
        arguments: {
            m: undefined,
            n: undefined,
            length: 2
        },

        //execution函數(shù)
        execution: , 

        //num變量
        saucxs: undefined
    },

    //作用域鏈
    scopeChain:[],

    //this指向
    this: window
}

1、funEC表示fun函數(shù)的執(zhí)行上下文(fun Execution Context 簡(jiǎn)寫(xiě)為funEC);

2、funEC的變量對(duì)象中arguments屬性,上面這樣寫(xiě)只是為了理解,在瀏覽器中展示以類(lèi)數(shù)組的方式展示的

3、表示的是execution函數(shù)在堆內(nèi)存地址的引用

說(shuō)明:創(chuàng)建變量對(duì)象發(fā)生在預(yù)編譯階段,還沒(méi)有進(jìn)入到執(zhí)行階段,該變量對(duì)象都不能訪問(wèn)的,因?yàn)榇藭r(shí)的變量對(duì)象中的變量屬性尚未賦值,值仍為undefined,只有在進(jìn)行執(zhí)行階段,變量中的變量屬性才進(jìn)行賦值后,變量對(duì)象(Variable Object)轉(zhuǎn)為活動(dòng)對(duì)象(Active Object)后,才能進(jìn)行訪問(wèn),這個(gè)過(guò)程就是VO->AO過(guò)程。

3.2.2創(chuàng)建作用域鏈

作用域鏈由當(dāng)前執(zhí)行環(huán)境的變量對(duì)象(未進(jìn)入到執(zhí)行階段前)與上層環(huán)境的一系列活動(dòng)對(duì)象組成,保證了當(dāng)前執(zhí)行還款對(duì)符合訪問(wèn)權(quán)限的變量和函數(shù)有序訪問(wèn)。

理解清楚作用域鏈可以幫助我們理解js很多問(wèn)題包括閉包問(wèn)題等,下面我們結(jié)合一個(gè)例子來(lái)理解一下作用域鏈。

var num = 30;

function test() {
    var a = 10;

    function innerTest() {
        var b = 20;

        return a + b
    }

    innerTest()
}

test()

在上面例子中,當(dāng)執(zhí)行到調(diào)用innerTest函數(shù),進(jìn)入到innerTest函數(shù)環(huán)境。全局執(zhí)行上下文和test函數(shù)執(zhí)行上下文已進(jìn)入到執(zhí)行階段,innerTest函數(shù)執(zhí)行上下文在預(yù)編譯階段創(chuàng)建變量對(duì)象,所以他們的活動(dòng)對(duì)象和變量對(duì)象分別是AO(global),AO(test)和VO(innerTest),而innerTest的作用域鏈由當(dāng)前執(zhí)行環(huán)境的變量對(duì)象(未進(jìn)入到執(zhí)行階段前)與上層環(huán)境的一系列活動(dòng)對(duì)象組成,如下:

innerTestEC = {

    //變量對(duì)象
    VO: {b: undefined}, 

    //作用域鏈
    scopeChain: [VO(innerTest), AO(test), AO(global)],  
    
    //this指向
    this: window
}

我們這里可以直接使用數(shù)組表示作用域鏈,作用域鏈的活動(dòng)對(duì)象或者變量對(duì)象可以直接理解成作用域。

1、作用域鏈的第一項(xiàng)永遠(yuǎn)是當(dāng)前作用域(當(dāng)前上下文的變量對(duì)象或者活動(dòng)對(duì)象);

2、最后一項(xiàng)永遠(yuǎn)是全局作用域(全局上下文的活動(dòng)對(duì)象);

3、作用域鏈保證了變量和函數(shù)的有序訪問(wèn),查找方式是沿著作用域鏈從左至右查找變量或者函數(shù),找到則會(huì)停止找,找不到則一直查找全局作用域,再找不到就會(huì)排除錯(cuò)誤。

3.2.3閉包

什么是閉包?思考一下

看一下簡(jiǎn)單的例子

function foo() {
    var num = 20;

    function bar() {
        var result = num + 20;

        return result
    }

    bar()
}

foo()

因?yàn)閷?duì)于閉包的有很多的不同理解,包括我看一些書(shū)籍(js高級(jí)程序設(shè)計(jì)),我這直接以瀏覽器解析,以瀏覽器的閉包為準(zhǔn)來(lái)分析閉包,如圖

如圖所示,谷歌瀏覽器理解的閉包是foo,那么按照瀏覽器的標(biāo)準(zhǔn)是如何定義的閉包,自己總結(jié)為三點(diǎn):

1、在函數(shù)內(nèi)部定義新函數(shù)

2、新函數(shù)訪問(wèn)外層函數(shù)的局部變量,即訪問(wèn)外層函數(shù)環(huán)境的活動(dòng)對(duì)象屬性

3、新函數(shù)執(zhí)行,創(chuàng)建新函數(shù)的執(zhí)行上下文,外層函數(shù)即為閉包

3.2.4確定this指向

1、在全局環(huán)境下,全局執(zhí)行的上下文中變量對(duì)象的this屬性指向?yàn)閣indow;

2、在函數(shù)環(huán)境下的this指向比較靈活,需要根據(jù)執(zhí)行環(huán)境和執(zhí)行方法確定,列舉典型例子來(lái)分析

四、總結(jié)

由于涉及到的內(nèi)容過(guò)多,下一次將第三階段(執(zhí)行階段)多帶帶分離出來(lái)。另開(kāi)出新文章詳細(xì)分析,主要介紹js執(zhí)行階段中的同步任務(wù)執(zhí)行和異步任務(wù)執(zhí)行機(jī)制(事件循環(huán)(Event Loop))。

五、參考書(shū)籍

你不知道的javascript(上卷)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/109701.html

相關(guān)文章

  • javascript引擎執(zhí)行過(guò)程理解--語(yǔ)法分析和預(yù)編譯階段

    摘要:所以覺(jué)得把這個(gè)執(zhí)行的詳細(xì)過(guò)程整理一下,幫助更好的理解。類(lèi)似的語(yǔ)法報(bào)錯(cuò)的如下圖所示三預(yù)編譯階段代碼塊通過(guò)語(yǔ)法分析階段之后,語(yǔ)法都正確的下回進(jìn)入預(yù)編譯階段。另開(kāi)出新文章詳細(xì)分析,主要介紹執(zhí)行階段中的同步任務(wù)執(zhí)行和異步任務(wù)執(zhí)行機(jī)制事件循環(huán)。 一、概述 js是一種非常靈活的語(yǔ)言,理解js引擎的執(zhí)行過(guò)程對(duì)于我們學(xué)習(xí)js是非常有必要的??戳撕芏噙@方便文章,大多數(shù)是講的是事件循環(huán)(event loo...

    molyzzx 評(píng)論0 收藏0
  • javascript引擎執(zhí)行過(guò)程理解--執(zhí)行階段

    摘要:如果對(duì)語(yǔ)法分析和預(yù)編譯,還有疑問(wèn)引擎執(zhí)行的過(guò)程的理解語(yǔ)法分析和預(yù)編譯階段。參與執(zhí)行過(guò)程的線程分別是引擎線程也稱(chēng)為內(nèi)核,負(fù)責(zé)解析執(zhí)行腳本程序的主線程例如引擎。以上便是引擎執(zhí)行宏任務(wù)的整個(gè)過(guò)程。 一、概述 js引擎執(zhí)行過(guò)程主要分為三個(gè)階段,分別是語(yǔ)法分析,預(yù)編譯和執(zhí)行階段,上篇文章我們介紹了語(yǔ)法分析和預(yù)編譯階段,那么我們先做個(gè)簡(jiǎn)單概括,如下: 1、語(yǔ)法分析: 分別對(duì)加載完成的代碼塊進(jìn)行語(yǔ)法...

    SnaiLiu 評(píng)論0 收藏0
  • javascript引擎執(zhí)行過(guò)程理解--執(zhí)行階段

    摘要:如果對(duì)語(yǔ)法分析和預(yù)編譯,還有疑問(wèn)引擎執(zhí)行的過(guò)程的理解語(yǔ)法分析和預(yù)編譯階段。參與執(zhí)行過(guò)程的線程分別是引擎線程也稱(chēng)為內(nèi)核,負(fù)責(zé)解析執(zhí)行腳本程序的主線程例如引擎。以上便是引擎執(zhí)行宏任務(wù)的整個(gè)過(guò)程。一、概述 js引擎執(zhí)行過(guò)程主要分為三個(gè)階段,分別是語(yǔ)法分析,預(yù)編譯和執(zhí)行階段,上篇文章我們介紹了語(yǔ)法分析和預(yù)編譯階段,那么我們先做個(gè)簡(jiǎn)單概括,如下: 1、語(yǔ)法分析: 分別對(duì)加載完成的代碼塊進(jìn)行語(yǔ)法檢驗(yàn),語(yǔ)...

    Achilles 評(píng)論0 收藏0
  • 《你不知道javascript》筆記_作用域與閉包

    摘要:建筑的頂層代表全局作用域。實(shí)際的塊級(jí)作用域遠(yuǎn)不止如此塊級(jí)作用域函數(shù)作用域早期盛行的立即執(zhí)行函數(shù)就是為了形成塊級(jí)作用域,不污染全局。這便是閉包的特點(diǎn)吧經(jīng)典面試題下面的代碼輸出內(nèi)容答案?jìng)€(gè)如何處理能夠輸出閉包方式方式下一篇你不知道的筆記 下一篇:《你不知道的javascript》筆記_this 寫(xiě)在前面 這一系列的筆記是在《javascript高級(jí)程序設(shè)計(jì)》讀書(shū)筆記系列的升華版本,旨在將零碎...

    galaxy_robot 評(píng)論0 收藏0
  • JS學(xué)習(xí)系列 01 - 編譯原理和作用域

    摘要:的抽象語(yǔ)法樹(shù)中可能如下圖所示代碼生成將轉(zhuǎn)換為可執(zhí)行代碼的過(guò)程被稱(chēng)為代碼生成。如果是,編譯器會(huì)忽略該聲明,繼續(xù)進(jìn)行編譯,否則它會(huì)要求在當(dāng)前作用域的集合中聲明一個(gè)新的變量,并命名為。 在學(xué)習(xí) javascript 的過(guò)程中,我們第一步最應(yīng)該了解和掌握的就是作用域,與之相關(guān)還有程序是怎么編譯的,變量是怎么查找的,js 引擎是什么,引擎和作用域的關(guān)系又是什么,這些是 javascript 這門(mén)...

    jkyin 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<