欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳釋JavaScript執(zhí)行環(huán)境與執(zhí)行棧

 更新時(shí)間:2019年04月02日 16:02:56   作者:為愛(ài)心太軟  
一句話就可以概括:代碼 ( 包括函數(shù) ) 執(zhí)行時(shí)所需要的所有信息就是執(zhí)行環(huán)境。由于 ES 歷經(jīng)多個(gè)版本,所以執(zhí)行環(huán)境的標(biāo)準(zhǔn)也一直在變。文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧

執(zhí)行環(huán)境

執(zhí)行環(huán)境 ( 也稱"執(zhí)行上下文" ) 可以說(shuō)是 JavaScript 最重要的一個(gè)概念。那么執(zhí)行環(huán)境到底是什么呢?一句話就可以概括:代碼 ( 包括函數(shù) ) 執(zhí)行時(shí)所需要的所有信息就是執(zhí)行環(huán)境。由于 ES 歷經(jīng)多個(gè)版本,所以執(zhí)行環(huán)境的標(biāo)準(zhǔn)也一直在變,下面列出了三個(gè)主要的版本內(nèi)容:

ES3 標(biāo)準(zhǔn)中的執(zhí)行環(huán)境

  • scope:作用域,如果有作用域嵌套的情況就稱作"作用域鏈"。
  • variable object:變量對(duì)象,用于存儲(chǔ)標(biāo)識(shí)符的特殊對(duì)象。
  • this value:this 值。

*標(biāo)識(shí)符:包括變量、函數(shù)名、屬性名和函數(shù)的參數(shù)。

ES5 標(biāo)準(zhǔn)中的執(zhí)行環(huán)境

  • variable environment:變量環(huán)境,當(dāng)聲明變量時(shí)使用。
  • lexical environment:詞法環(huán)境,當(dāng)獲取標(biāo)識(shí)符值時(shí)使用。
  • this value:this 值。

ES6 標(biāo)準(zhǔn)中的執(zhí)行環(huán)境

  • variable environment:變量環(huán)境,當(dāng)聲明變量時(shí)使用。
  • lexical environment:詞法環(huán)境,當(dāng)獲取標(biāo)識(shí)符值或者 this 值時(shí)使用。

*在 ES6 中,執(zhí)行環(huán)境中實(shí)際增加了不少內(nèi)容,我們這里只介紹了普通函數(shù)執(zhí)行時(shí)所需要的內(nèi)容。

執(zhí)行棧

當(dāng)打開(kāi)網(wǎng)頁(yè)或?yàn)g覽器時(shí),宿主環(huán)境(1)會(huì)將代碼傳遞給引擎(2)去執(zhí)行,引擎首先會(huì)創(chuàng)建一個(gè)全局執(zhí)行環(huán)境。全局環(huán)境中的代碼自上而下有順序的執(zhí)行,當(dāng)遇到一個(gè)函數(shù)時(shí),函數(shù)的環(huán)境被創(chuàng)建,函數(shù)中的代碼開(kāi)始執(zhí)行;而在函數(shù)執(zhí)行之后,控制權(quán)又返還給之前的環(huán)境。ES 這種類似于" 棧 "(3)的控制機(jī)制,稱為執(zhí)行棧。

(1) 宿主環(huán)境:瀏覽器或者 Node 環(huán)境。
(2) 引擎:從頭到尾負(fù)責(zé)整個(gè) JavaScript 代碼的編譯及執(zhí)行過(guò)程。
(3) 棧:一種遵循" 后進(jìn)先出 "原則的有序數(shù)據(jù)集合,可以簡(jiǎn)單理解為使用 push() 和 pop() 操作數(shù)組。

例子:

console.log(1);

function pFn() {
 console.log(2);
 (function cFn() {
 console.log(3);
 }());
 console.log(4);
}
pFn();

console.log(5);
//輸出:1 2 3 4 5

示意圖:

我們可以通過(guò)瀏覽器,直觀的看一下執(zhí)行棧的形式:

編譯原理

我們知道,執(zhí)行環(huán)境中有很多非常有用的" 工具 “,這些” 工具 “會(huì)協(xié)助引擎完成整個(gè)函數(shù)的執(zhí)行工作。例如,ES3 標(biāo)準(zhǔn)中的作用域,它會(huì)協(xié)助引擎查找當(dāng)前環(huán)境中所有標(biāo)識(shí)符的定義的位置;變量對(duì)象,幫助引擎保存環(huán)境中的變量和函數(shù)。當(dāng)然,這些工作大部分情況下發(fā)生在代碼執(zhí)行前的幾微秒之內(nèi),稱之為” 編譯階段 "。JavaScript 的整個(gè)編譯階段比較復(fù)雜,一般會(huì)經(jīng)歷詞法分析、語(yǔ)法分析、代碼生成、性能優(yōu)化等步驟,這里不做深入討論。

下面我們舉例說(shuō)明,看看當(dāng)函數(shù) fn 執(zhí)行的時(shí)候,引擎是如何工作的:

var b=1;
function fn(){
 var a = 1;
 return a+b;
}
fn();

1、首先,遇到 var a,引擎會(huì)詢問(wèn)作用域是否已經(jīng)有一個(gè)該名稱的變量存在于同一個(gè)作用域中。如果存在,引擎會(huì)忽略該聲明,繼續(xù)進(jìn)行編譯;很顯然不存在,所以引擎會(huì)在當(dāng)前作用域中聲明一個(gè)新的變量,并命名為 a ( 此時(shí)還沒(méi)有賦值,默認(rèn)為 undefined )。

2、第二步,又遇到 a,引擎會(huì)首先詢問(wèn)作用域,在當(dāng)前的作用域中是否存在一個(gè)叫作 a 的變量,很顯然存在,所以引擎就會(huì)使用這個(gè)變量;遇到 b,引擎對(duì)作用域做出同樣的詢問(wèn),很顯然不存在,所以引擎會(huì)到外層嵌套的作用域中繼續(xù)查找,在全局作用域找到了該變量,引擎就會(huì)將 1 賦值給變量 b 。

3、經(jīng)過(guò)以上兩步,函數(shù) fn 環(huán)境中出現(xiàn)的所有標(biāo)識(shí)符的值已經(jīng)基本鎖定,那么引擎就會(huì)立即自上而下開(kāi)始執(zhí)行代碼。為變量 a 賦值 1,計(jì)算 1+1 的值并返回它。

4、最后一步,函數(shù) fn 的環(huán)境銷毀,退出執(zhí)行棧,將控制權(quán)返還給全局環(huán)境。

變量提升的原因

在編譯階段,引擎會(huì)聲明變量和函數(shù),但不會(huì)對(duì)變量進(jìn)行賦值,這主要是出于對(duì)性能的考慮。變量被聲明,但是不一定會(huì)在后面使用到,如果沒(méi)有使用卻賦了值,只是白白浪費(fèi)內(nèi)存而已。上面例子中的全局變量 b ,在函數(shù) fn 沒(méi)有執(zhí)行之前,也不會(huì)賦值,直到函數(shù)中使用了這個(gè)變量,才不得不去加載數(shù)字 1。簡(jiǎn)單的說(shuō),var a 這段代碼發(fā)生在編譯階段,而 =1 這段代碼會(huì)根據(jù)實(shí)際情況,發(fā)生在執(zhí)行階段,這也就是" 變量提升 "的原因。另外需要注意的是,函數(shù)聲明的是整個(gè)函數(shù)體( 因?yàn)楹瘮?shù)聲明不存在賦值操作),而且優(yōu)先級(jí)高于同名的變量。

例子1:

console.log(fn()); //輸出:1
console.log(n); //輸出:undefined

function fn() {
 return 1;
}
var n = 2;

由于聲明發(fā)生在賦值的前面,上面例子1的代碼可以理解為下面的形式:

function fn() {
 return 1;
}
var n;

console.log(fn()); //輸出:1
console.log(n); //輸出:undefined

n = 2;

由于函數(shù)聲明優(yōu)先級(jí)高,因此同名變量聲明會(huì)被忽略,上面例子2的代碼可以理解為下面的形式:

function fn() {
 console.log(1);
}

//由于函數(shù)聲明優(yōu)先級(jí)高,因此這個(gè)變量聲明會(huì)被忽略
//var fn;

fn(); //輸出:1

fn = function() {
 console.log(2);
}

*變量提升并非物理意義上的順序改變,代碼執(zhí)行的順序還是按照你書寫代碼時(shí)的順序在執(zhí)行。只是由于,變量聲明發(fā)生在代碼的編譯階段,而變量賦值卻發(fā)生在代碼的執(zhí)行階段,時(shí)間上的差異導(dǎo)致了這種現(xiàn)象。

運(yùn)行時(shí)流程圖

綜合以上的內(nèi)容,JavaScript 的運(yùn)行時(shí)流程圖如下:

相關(guān)文章

  • Perl Substr()函數(shù)及函數(shù)的應(yīng)用

    Perl Substr()函數(shù)及函數(shù)的應(yīng)用

    這篇文章主要介紹了Perl Substr()函數(shù)及函數(shù)的應(yīng)用,需要的朋友可以參考下
    2015-12-12
  • 詳解JS內(nèi)存空間

    詳解JS內(nèi)存空間

    因?yàn)镴avaScript具有自動(dòng)垃圾回收機(jī)制,所以對(duì)于前端開(kāi)發(fā)來(lái)說(shuō),內(nèi)存空間并不是一個(gè)經(jīng)常被提及的概念。特別是很多不是計(jì)算機(jī)專業(yè)的朋友在進(jìn)入到前端之后,會(huì)對(duì)內(nèi)存空間的認(rèn)知比較模糊,甚至有些人干脆就是一無(wú)所知。為了解決大家的疑惑,本文將詳細(xì)介紹JS內(nèi)存空間
    2021-06-06
  • 原生js實(shí)現(xiàn)圖片輪播特效

    原生js實(shí)現(xiàn)圖片輪播特效

    這篇文章主要介紹了原生js實(shí)現(xiàn)圖片輪播特效,適合用于商品展示,實(shí)現(xiàn)最簡(jiǎn)單的廣告輪播效果,感興趣的小伙伴們可以參考一下
    2015-12-12
  • 原生js實(shí)現(xiàn)復(fù)制對(duì)象、擴(kuò)展對(duì)象 類似jquery中的extend()方法

    原生js實(shí)現(xiàn)復(fù)制對(duì)象、擴(kuò)展對(duì)象 類似jquery中的extend()方法

    jq的extend()方法能很方便的實(shí)現(xiàn)擴(kuò)展對(duì)象方法,這里要實(shí)現(xiàn)的是:原生js實(shí)現(xiàn)復(fù)制對(duì)象,擴(kuò)展對(duì)象,類似jq中的extend()方法,需要的朋友可以參考下
    2014-08-08
  • JS使用JSON作為參數(shù)實(shí)例分析

    JS使用JSON作為參數(shù)實(shí)例分析

    這篇文章主要介紹了JS使用JSON作為參數(shù),結(jié)合實(shí)例形式分析了ajax傳遞json數(shù)據(jù)及數(shù)據(jù)處理的相關(guān)技巧,需要的朋友可以參考下
    2016-06-06
  • bootstrap校驗(yàn)laydate起止日期聯(lián)動(dòng)失效問(wèn)題及解決方法

    bootstrap校驗(yàn)laydate起止日期聯(lián)動(dòng)失效問(wèn)題及解決方法

    這篇文章主要介紹了bootstrap校驗(yàn)laydate起止日期聯(lián)動(dòng)失效問(wèn)題,項(xiàng)目中用到bootstrapValidator,以及l(fā)aydate(by:賢心,插件效果美觀),本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2023-01-01
  • 小程序簡(jiǎn)單兩欄瀑布流效果的實(shí)現(xiàn)

    小程序簡(jiǎn)單兩欄瀑布流效果的實(shí)現(xiàn)

    這篇文章主要介紹了小程序簡(jiǎn)單兩欄瀑布流效果的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-12-12
  • jstree單選功能的實(shí)現(xiàn)方法

    jstree單選功能的實(shí)現(xiàn)方法

    這篇文章主要介紹了 jstree單選功能的實(shí)現(xiàn)方法,需要的朋友可以參考下
    2017-06-06
  • 用JS提交參數(shù)創(chuàng)建form表單在FireFox中遇到的問(wèn)題

    用JS提交參數(shù)創(chuàng)建form表單在FireFox中遇到的問(wèn)題

    在一個(gè)前端頁(yè)面上,需要通過(guò)JavaScript來(lái)提交參數(shù),使用JS創(chuàng)建form表單,將參數(shù)append到表單中進(jìn)行提交,接下來(lái)將介紹如何操作與實(shí)現(xiàn)
    2013-01-01
  • JavaScript中函數(shù)的防抖與節(jié)流詳解

    JavaScript中函數(shù)的防抖與節(jié)流詳解

    這篇文章主要為大家詳細(xì)介紹了JavaScript中函數(shù)的防抖與節(jié)流,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下,希望能夠給你帶來(lái)幫助
    2022-02-02

最新評(píng)論