高級前端進階(五)

来源:https://www.cnblogs.com/ywjbokeyuan/archive/2022/05/09/16011512.html
-Advertisement-
Play Games

詳解JavaScript中的事件迴圈機制!!! 一、簡單講解 這個大家應該或多或少都知道的 for (var i = 0; i < 10; i++) { setTimeout(() => { console.log(i); // 輸出10個10 }); } 解析:先執行for迴圈,迴圈疊加i,然後再 ...


詳解JavaScript中的事件迴圈機制!!!

一、簡單講解

這個大家應該或多或少都知道的

for (var i = 0; i < 10; i++) {
  setTimeout(() => {
    console.log(i); // 輸出10個10
  });
}

解析:先執行for迴圈,迴圈疊加i,然後再執行setTimeout 10遍,所以會輸出10個10
變體:

for (let i = 0; i < 10; i++) {
  setTimeout(() => {
    console.log(i); // 依次輸出0-9
  });
}

我們知道var跟let本質區別就是作用域的問題,所以會聯想到let導致的,但在這一點上,並不是作用域問題,因為從事件迴圈機制來解釋是有問題的
以上的代碼等價於

for (var i = 0; i < 10; i++) {
  (function (i) {
    setTimeout(() => {
      console.log(i);
    });
  })(i); // 立即執行函數,以上的let應該是將代碼特殊處理了下
}

立即執行函數:函數聲明後立即執行。
從事件迴圈的角度來說,應該先執行for迴圈將i疊加到10,執行完後再去執行for迴圈體(setTimeout),此時的i變成了10,所以每次輸出都是10,
這裡使用let,應該是特殊處理了一下的。

二、深入講解

我們知道JavaScript語言是單線程的,至於為啥是單線程?
假設有兩個線程,一個在頁面上新增一個div,另一個線程在頁面上刪除div,那最終聽誰的?
那JavaScript怎麼實現非同步的呢?
在JavaScript中,有兩類任務:同步任務和非同步任務。
同步任務:普通的任務,依次從上往下執行。
非同步任務:又分為巨集任務、微任務。

巨集任務:setTimeout跟setInterval
微任務:Promise().then() 這裡要註意一下,Promise方法裡面的是同步任務,then裡面的才是微任務
執行順序:先執行同步任務,遇到非同步任務,將其放入到巨集任務或者微任務隊列中,然後優先執行微任務,接下來再去執行巨集任務。

簡單的例子:

setTimeout(function() {
    console.log(1)
}, 0);

new Promise(function(resolve, reject) {
    console.log(2); // 這裡是同步任務
    resolve();
}).then((res) => {
    console.log(3);
})
console.log(4);
// 輸出結果是 2  4  3  1

解析:從上往下執行,setTimeout是巨集任務,放到巨集任務隊列中,
Promise裡面的是同步任務,所以先執行,輸出2,then裡面的是微任務,放到微任務隊列中,
最後一個是同步任務,執行,輸出4,
然後執行微任務,輸出3
最後執行巨集任務,輸出1

來點難度的:

console.log(1);

setTimeout(function () {
  console.log(2);
}, 0);

setTimeout(function () {
  console.log(3);

  setTimeout(function () {
    console.log(4);
  }, 0);
}, 0);

new Promise(function (resolve, reject) {
  console.log(5);
  resolve();
}).then((res) => {
  console.log(6);
  new Promise(function (resolve, reject) {
    console.log(7);
    resolve();
  }).then((res) => {
    console.log(8);
  });
});

new Promise(function (resolve, reject) {
  console.log(9);
  resolve();
})
  .then((res) => {
    console.log(10);
  })
  .then((res) => {
    console.log(11);
  });

console.log(12);
// 輸出 1  5   9   12
//      6  7  10   8   11
//      2  3  4

解析:原理跟上面一樣,不過需要註意的是,8跟11的順序:,在這裡then的層級,將各個Promise裡面第一層的then放在一起,第二層的then放在一起,依此類推,
然後依次執行第一層的,執行完第一層,接下來執行完第二層,依此類推。
第一層(6,7,10)
第二層(8,11)
所以先輸出8, 再輸出11的。

再來一個(也最可能出錯或者無法理解的):

console.log(1);
async function fn() {
  console.log(2);
  await console.log(3);
  console.log(4); // 這一步,你應該會有問題
}
setTimeout(() => {
  console.log(5);
}, 0);
fn();
new Promise((resolve) => {
  console.log(6);
  resolve();
}).then(() => {
  console.log(7);
});
console.log(8);
// 輸出:1  2  3   6   8   4  7  5

解析:async await是Promise的語法糖,只是針對寫法上的優化
將async await翻譯成Promise:

async function fn() {
  console.log(2);
  await console.log(3);
  console.log(4); // 這一步,你應該會有問題
}
// 等價於
function fn() {
  return new Promise((resolve, reject) => {
    console.log(2);
    resolve(
      (() => {
        console.log(3);
      })() // 立即執行函數
    );
  }).then(() => {
    console.log(4);
  });
}

這樣,你應該能夠明白,為啥輸出3之後不是立即輸出4了吧!

再來一道加深鞏固的:

console.log(1);
async function fn() {
  console.log(2);
  await console.log(3);
  await console.log(4);
  console.log(5);
}
setTimeout(() => {
  console.log(6);
}, 2000);
setTimeout(() => {
  console.log(7);
}, 1000);
fn();
new Promise((resolve) => {
  console.log(8);
  new Promise((resolve) => {
    console.log(9);
    resolve();
  }).then(() => {
    console.log(10);
  });
  resolve();
}).then(() => {
  console.log(11);
  new Promise((resolve) => {
    console.log(12);
    resolve();
  }).then(() => {
    console.log(13);
  });
});
console.log(14);
// 輸出 1  2  3  8  9  14
//      4  10 11 12 5  13
//      7  6 

我相信,你現在應該理解掌握了!

只要鑽的深,鐵杵都能給你磨成針!!!

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • SQL語言基礎 SQL (Structured Query Language:結構化查詢語言) 是用於管理關係資料庫管理系統(RDBMS)。 SQL 的範圍包括數據插入、查詢、更新和刪除,資料庫模式創建和修改,以及數據訪問控制。 本文主要記錄一些主要的SQL命令(比如 SELECT、UPDATE、D ...
  • 一、使用PIVOT實現行轉列 1、首先創建一個學生表 CREATE TABLE [dbo].[Students]( [stu_id] [int] IDENTITY(1,1) NOT NULL, [stu_name] [varchar](100) NULL, [stu_hobby] [varchar] ...
  • 在進行視頻通話過程中,用戶有時候會出現網路不好的情況,比如在進行多人視頻通話或者多人唱歌時,我們需要實時顯示用戶的網路質量。 ...
  • 本次上新,共計新增94個開源組件。組件涉及工具、網路、UI、圖形、音視頻等多種功能。 ...
  • 5月11日晚19:00,Hello HarmonyOS進階系列應用篇第二課《電腦視覺》直播如約而至。 ...
  • 隨著新技術的不斷演進,人工智慧已經廣泛地應用到教育、金融、物流、零售、交通、醫療等各個領域。而在AI高速發展的當下,高效開發變得更為重要,如何將創意想法與AI技術深度融合,迅速轉化為可落地的AI應用,是開發者在激烈競爭中制勝的關鍵。 為了助力開發者快速上線AI業務,為消費者提供創新AI體驗,HMS ...
  • 只有在ajax才能找回一點點主場了,vue中的ajax一天整完,內容還行,主要是對axios的運用。 明天按理說要開始vuex了,這個從來都是只耳聞沒有眼見過,明天來看看看看是個什麼神奇的東西。 一. 解決開發環境ajax跨域問題 1.配置代理(方法一) 首先我們能發起ajax請求的,xhr原生不推 ...
  • 大家好,我是半夏👴,一個剛剛開始寫文的沙雕程式員.如果喜歡我的文章,可以關註➕ 點贊 👍 加我微信:frontendpicker,一起學習交流前端,成為更優秀的工程師~關註公眾號:搞前端的半夏,瞭解更多前端知識! 點我探索新世界! 原文鏈接 ==>http://sylblog.xin/archi ...
一周排行
    -Advertisement-
    Play Games
  • 前言 本文將以 C# 語言來實現一個簡單的布隆過濾器,為簡化說明,設計得很簡單,僅供學習使用。 感謝@時總百忙之中的指導。 布隆過濾器簡介 布隆過濾器(Bloom filter)是一種特殊的 Hash Table,能夠以較小的存儲空間較快地判斷出數據是否存在。常用於允許一定誤判率的數據過濾及防止緩存 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • 「簡單有價值的事情長期堅持做」 這是成功最簡單,但也最難學的秘訣。不經過訓練,人很難意識到時間複利的威力。 仙劍奇俠傳的「十里坡劍神」和金庸群俠傳的「十級野球拳」,就是簡單的事情持之以恆反覆做,最後就有巨大的威力 唐家三少成為網文收入第一,最重要的一步是十四年從未斷日更 這樣的案例很多,一開始可能成 ...
  • 迎面走來了你的面試官,身穿格子衫,挺著啤酒肚,髮際線嚴重後移的中年男子。 手拿泡著枸杞的保溫杯,胳膊夾著MacBook,MacBook上還貼著公司標語:“我愛加班”。 面試開始,直入正題。 面試官: 看你簡歷上面寫著精通MySQL,我先問你事務的特性是什麼? 老生常談,這個還有誰不會背的嗎? 我: ...
  • 基礎知識 python是一門腳本語言,它是解釋執行的。 python使用縮進做為語法,而且python2環境下同一個py文件中不能同時存在tab和空格縮進,否則會出錯,建議在IDE中顯示縮進符。 python在聲明變數時不寫數據類型,可以type(xx)來獲取欄位的類型,然後可以int(),list ...
  • 為什麼要多線程下載 俗話說要以終為始,那麼我們首先要明確多線程下載的目標是什麼,不外乎是為了更快的下載文件。那麼問題來了,多線程下載文件相比於單線程是不是更快? 對於這個問題可以看下圖。 橫坐標是線程數,縱坐標是使用對應線程數下載對應文件時花費的時間,藍橙綠代表下載文件的大小,每個線程下載對應文件2 ...
  • 詳細講解python爬蟲代碼,爬微博搜索結果的博文數據。 爬取欄位: 頁碼、微博id、微博bid、微博作者、發佈時間、微博內容、轉發數、評論數、點贊數。 爬蟲技術: 1、requests 發送請求 2、datetime 時間格式轉換 3、jsonpath 快速解析json數據 4、re 正則表達式提... ...
  • 背景: 一般我們可以用HashMap做本地緩存,但是HashMap功能比較弱,不支持Key過期,不支持數據範圍查找等。故在此實現了一個簡易的本地緩存,取名叫fastmap。 功能: 1.支持數據過期 2.支持等值查找 3.支持範圍查找 4.支持key排序 實現思路: 1.等值查找採用HashMap2 ...
  • 目錄 一.簡介 二.效果演示 三.源碼下載 四.猜你喜歡 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 基礎 零基礎 OpenGL (ES) 學習路線推薦 : OpenGL (ES) 學習目錄 >> OpenGL ES 轉場 零基礎 O ...
  • 本章是系列文章的第八章,用著色演算法進行寄存器的分配過程。 本文中的所有內容來自學習DCC888的學習筆記或者自己理解的整理,如需轉載請註明出處。周榮華@燧原科技 寄存器分配 寄存器分配是為程式處理的值找到存儲位置的問題 這些值可以存放到寄存器,也可以存放在記憶體中 寄存器更快,但數量有限 記憶體很多,但 ...