国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

33 個 js 核心概念(一):函數調用棧,執行上下文與變量對象

ZHAO_ / 2366人閱讀

摘要:最先執行完畢的一定是最里面的函數,執行過后彈出調用棧,接著執行上一層函數,直至所有函數執行完,調用棧清空。到這里你應該就會明白,上面函數調用棧,就是生成了一個函數的執行上下文。

前言 為什么會有這篇文章?

在書籍或博客上,我們經常會看到「作用域鏈」、「閉包」、「變量提升」等概念,說明一個問題 —— 它們很重要。

但很多時候,對于這些概念,看的時候覺得自己已經明白了,可過不了多久,再讓你說一說,可能就說不清楚了,之所以會這樣,是因為我們對于 JavaScript 這門語言的運行機制不清楚。

我相信搞明白了今天所講的內容,會對你理解那些知識大有裨益!

函數調用棧(call stack) 1. 什么是棧?

類似 js 中的數組,棧也是用來存儲數據的一種數據結構。他的特點是后進先出(LIFO)。

與之相對的一種數據結構稱為隊列,隊列的特點是先進先出(FIFO)

可以想象這樣一種場景:小明和同學們放學回家,老師讓他在排在隊伍的最前面,他們每天回家路上都要經過一個胡同,小明每次都是第一個進入胡同,肯定也是第一個出來,這就是所謂「先進先出」。

可是有一天,小明他們走到胡同里發現胡同口停了一輛車,把胡同給堵死了,沒辦法,他們只能隊頭變隊尾往回撤,這時候,小明雖然最先進入胡同,卻只能最后出去,最先出去的是排在隊尾的小華,也就是「后進先出」。

2. 什么叫函數調用棧?

在 js 中函數的調用也遵照這樣以一個原則:最先調用的函數先放到調用棧中,假如這個函數內部又調用了別的函數,那么這個內部函數就接著被放入調用棧中,直至不再有函數調用。最先執行完畢的一定是最里面的函數,執行過后彈出調用棧,接著執行上一層函數,直至所有函數執行完,調用棧清空。

這樣說可能會不太明白,舉個例子:

</>復制代碼

  1. // 其他語句
  2. function first() {
  3. console.log("first")
  4. function second() {
  5. console.log("second")
  6. }
  7. second();
  8. third();
  9. // 其他語句
  10. }
  11. //其他語句
  12. function third() {
  13. console.log("third")
  14. }
  15. // 調用 first
  16. first();

在上述代碼中,首先調用的是函數 first, 此時 first 進入函數棧,接著在 first 中調用函數 second,second 入棧,當 second 執行完畢后,second 出棧,third 入棧,接著 third 執行完出棧,執行 first 其他代碼,直至 first 執行完,函數棧清空。

執行上下文(Execution Context) 1. 什么是執行上下文?

js 代碼在執行時,會進入一個執行環境,它會形成一個作用域。這個執行環境,便是執行上下文。

JavaScript 主要有三種執行環境:

全局執行環境: 代碼開始執行時首先進入的環境。

函數環境:函數調用時,會開始執行函數中的代碼。

eval:不建議使用,可忽略。

2. 執行上下文的生命周期

上面講到 js 代碼執行時會生成一個執行上下文。而這個執行上下文的周期,分為兩個階段:

創建階段。這個階段會生成變量對象(VO),建立作用域鏈以及確定 this 的值。

執行階段。這個階段進行變量賦值,函數引用及執行代碼。

到這里你應該就會明白,上面函數調用棧,就是生成了一個函數的執行上下文。

3. 什么是執行棧?

執行上下文也同樣遵循函數調用棧的規則,無非就是多加了一層 —— 全局執行上下文,函數執行完后會跳出執行棧,而全局執行上下文,會在關閉瀏覽器后跳出執行棧。

還是上面的例子,我們看一下執行棧。

變量對象 1. 什么叫變量對象?

從上面其實可以得到答案,變量對象是 js 代碼在進入執行上下文時,js 引擎在內存中建立的一個對象,用來存放當前執行環境中的變量。

2. 變量對象(VO)的創建過程

變量對象的創建,是在執行上下文創建階段,依次經過以下三個過程:

創建 arguments 對象。對于函數執行環境,首先查詢是否有傳入的實參,如果有,則會將參數名是實參值組成的鍵值對放入arguments 對象中,否則,將參數名和 undefined,組成的鍵值對放入 arguments 對象中。

</>復制代碼

  1. function bar(a, b, c) {
  2. console.log(arguments); // [2, 4]
  3. console.log(arguments[2]); // undefined
  4. }
  5. bar(2,4)

檢查當前環境中的函數聲明。當遇到同名的函數時,后面的會覆蓋前面的。

</>復制代碼

  1. console.log(a); // function a() {console.log("fjdsfs") }
  2. function a() {
  3. console.log("24");
  4. }
  5. function a() {
  6. console.log("fjdsfs")
  7. }

在上面的例子中,在執行第一行代碼之前,函數聲明已經創建完成,后面的對之前的聲明進行了覆蓋。

檢查當前環境中的變量聲明并賦值為undefined當遇到同名的函數聲明,為了避免函數被賦值為 undefined ,會忽略此聲明

</>復制代碼

  1. console.log(a); // function a() {console.log("fjdsfs") }
  2. console.log(b); // undefined
  3. function a() {
  4. console.log("24");
  5. }
  6. function a() {
  7. console.log("fjdsfs");
  8. }
  9. var b = "bbbbbbbb";
  10. var a = 46;

在上例我們可以看到,在代碼之前前,a 仍舊是一個函數,而 b 是 undefined。

根據以上三個步驟,對于變量提升也就知道是怎么回事了。

3. 變量對象變為活動對象

執行上下文的第二個階段,稱為執行階段,在此時,會進行變量賦值,函數引用并執行其他代碼,此時,變量對象變為活動對象。

我們還是舉上面的例子:

</>復制代碼

  1. console.log(a); // function a() {console.log("fjdsfs") }
  2. console.log(b); // undefined
  3. function a() {
  4. console.log("24");
  5. }
  6. function a() {
  7. console.log("fjdsfs");
  8. }
  9. var b = "bbbb";
  10. console.log(b); // "bbbb"
  11. var a = 46;
  12. console.log(a); // 46
  13. var b = "hahahah";
  14. console.log(b); // "hahah"

在上面的代碼中,代碼真正開始執行是從第一行 console.log() 開始的,自這之前,執行上下文是這樣的:

</>復制代碼

  1. // 創建過程
  2. EC= {
  3. VO: {}; // 創建變量對象
  4. scopeChain: {}; // 作用域鏈
  5. }
  6. VO = {
  7. argument: {...}; // 當前為全局上下文,所以這個屬性值是空的
  8. a: // 函數 a 的引用地址
  9. b: undefiend // 見上文創建變量對象的第三步
  10. }

根據步驟,首先是 arguments 對象的創建;其次,是檢查函數的聲明,此時,函數 a 聲明了兩次,后一次將覆蓋前一次;最后,是檢查變量的聲明,先聲明了變量 b,將它賦值為 undefined,接著遇到 a 的聲明,由于 a 已經聲明為了一個函數,所以,此條聲明將會被忽略。

到此,變量對象的創建階段完成,接下來時執行階段,我們一步一步來。

執行 console.log(a),我們知道,此時 a 是第二個函數,所以會輸出function a() {...};

執行 console.log(b),不出我們所料,將會輸出 undefined;

執行賦值操作: b = "bbbb";

執行 console.log(b) ,此時,b 已經賦值,所以會輸出 "bbbb";

執行賦值操作: a = 46;

執行 console.log(a) ,此時,a 的值變為 46。

執行賦值操作: b = "hahahah";

執行 console.log(b), b 已經被重新賦值,輸出 hahahah。

由上面我們可以看到,在執行階段,變量對象是跟著代碼不斷變化的,此時,我們把變量對象成為活動對象。

執行到最后一步時,執行上下文變成了這樣。

</>復制代碼

  1. // 執行階段
  2. EC = {
  3. VO = {};
  4. scopeChain: {};
  5. }
  6. // VO ---- AO
  7. AO = {
  8. argument: {...};
  9. a: 46;
  10. b: "hahahah";
  11. this: window;
  12. }

以上,就是變量對象在代碼執行前及執行時的變化。

剛開始就說過,這部分概念將會對你理解后面的知識有很大的幫助,所以剛開始接觸的話可能會有些晦澀,建議就是認真讀兩遍,結合后面的知識,經常回過頭來看看。

最后留一道題,給大家作為練手,觀察觀察執行上下文及變量對象的變化。

</>復制代碼

  1. console.log(a);
  2. console.log(b);
  3. var a = 4;
  4. function a() {
  5. console.log("我是a1");
  6. b(3, 5);
  7. }
  8. var a = function a() {
  9. console.log("我是a2");
  10. b(3, 5);
  11. }
  12. var b = function (m, n) {
  13. console.log(arguments);
  14. console.log("b")
  15. }
  16. a();

</>復制代碼

  1. 原文地址:阿木木的博客

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99823.html

相關文章

  • 33 js 核心概念(二):數據類型

    摘要:舉個例子在上面的例子可以看到,我們聲明是一個數字,但是我們在之后將的值又改成了字符串和布爾值后面會講這些類型?;绢愋妥址硎疽粋€字符串,如。因此,我們可以寫一個函數,用來精確檢測類型。 showImg(https://segmentfault.com/img/remote/1460000017309509?w=850&h=572); 定義 1. 什么是數據類型? 數據類型,就是將...

    QiShare 評論0 收藏0
  • 春招季如何橫掃 Javascript 面試核心考點(基礎版)?

    摘要:當前函數執行完成后,當前函數的執行上下文出棧,并等待垃圾回收。作用域與作用域鏈到來有全局作用域函數作用域和塊級作用域新增。 引言 Javascript是前端面試的重點,本文重點梳理下 Javascript 中的常考知識點,然后就一些容易出現的題目進行解析。限于文章的篇幅,無法將知識點講解的面面俱到,本文只羅列了一些重難點,如果想要了解更多內容歡迎點擊我的博客。 一、變量類型 1.JS ...

    impig33 評論0 收藏0
  • 春招季如何橫掃 Javascript 面試核心考點(基礎版)?

    摘要:當前函數執行完成后,當前函數的執行上下文出棧,并等待垃圾回收。作用域與作用域鏈到來有全局作用域函數作用域和塊級作用域新增。 引言 Javascript是前端面試的重點,本文重點梳理下 Javascript 中的常考知識點,然后就一些容易出現的題目進行解析。限于文章的篇幅,無法將知識點講解的面面俱到,本文只羅列了一些重難點,如果想要了解更多內容歡迎點擊我的博客。 一、變量類型 1.JS ...

    jayce 評論0 收藏0
  • 理解JavaScript的核心知識點:This

    摘要:關鍵字計算為當前執行上下文的屬性的值。毫無疑問它將指向了這個前置的對象。構造函數也是同理。嚴格模式無論調用位置,只取顯式給定的上下文綁定的,通過方法傳入的第一參數,否則是。其實并不屬于特殊規則,是由于各種事件監聽定義方式本身造成的。 this 是 JavaScript 中非常重要且使用最廣的一個關鍵字,它的值指向了一個對象的引用。這個引用的結果非常容易引起開發者的誤判,所以必須對這個關...

    TerryCai 評論0 收藏0
  • 【譯】JavaScript 核心(第二版)

    摘要:技術上來說這個機制被稱為動態分配或代理。定義類一個類是一個正式的抽象集,它規定了對象的初始狀態和行為。技術上來說一個類表示構造函數原型的組合。因此構造函數創建對象并自動設置新創建實例的原型。第二次調用時,相同的上下文再次被壓入棧并恢復。 原文:JavaScript. The Core: 2nd Edition作者:Dmitry Soshnikov 文章其他語言版本:俄語 這篇文章是 ...

    dingding199389 評論0 收藏0

發表評論

0條評論

ZHAO_

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<