Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 日韩大片在线,日韩在线|中文,欧美成人欧美激情欧美风情

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          使用JS文件調(diào)用Google AdSense廣告的方

          使用JS文件調(diào)用Google AdSense廣告的方法

          網(wǎng)頁(yè)中插入 Google AdSense 廣告,一般將源代碼直接嵌入主題模板頁(yè)面。事實(shí)上 Google AdSense 支持并允許使用 JS 文件調(diào)用。當(dāng)然前提是不要因任何原因修改代碼,或手動(dòng)影響廣告的定位。

          對(duì)于通常的 HTML 靜態(tài)網(wǎng)站,一般的做法是將公共頭部和公共尾部都放到單獨(dú)的 JavaScript 文件里,例如 header.js 和 footer.js,這樣單獨(dú)編輯這兩個(gè) JS 文件,即可同時(shí)修改全部網(wǎng)站內(nèi)容,因此我們可以考慮把 Google AdSense 的代碼放到這個(gè)頭文件里。具體做法如下:

          首先,登陸 Google AdSense 后臺(tái),獲取廣告代碼,通常代碼如下:

          <script data-ad-client="ca-pub-YOUR-ID" async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>

          這樣,我們把如下 JavaScript 代碼放到 header.js 頭文件里即可,代碼如下。

          var js=document.createElement("script");

          js.setAttribute('data-ad-client', 'ca-pub-YOUR-ID');

          js.setAttribute('async', true);

          js.setAttribute('src', 'https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js');

          document.head.appendChild(js);

          上面的代碼里,需要把 ca-pub-YOUR-ID 替換為用戶自己ID號(hào)碼。

          這段代碼和原始的 Google AdSense 的 JavaScript 原理完全一樣,實(shí)際顯示效果也一樣。

          三元:https://juejin.im/post/5dd8b3a851882572f56b578f?utm_source=bigezhang.com#heading-6


          首先需要明白的是,機(jī)器是讀不懂 JS 代碼,機(jī)器只能理解特定的機(jī)器碼,那如果要讓 JS 的邏輯在機(jī)器上運(yùn)行起來(lái),就必須將 JS 的代碼翻譯成機(jī)器碼,然后讓機(jī)器識(shí)別。JS屬于解釋型語(yǔ)言,對(duì)于解釋型的語(yǔ)言說(shuō),解釋器會(huì)對(duì)源代碼做如下分析:

          1.通過(guò)詞法分析和語(yǔ)法分析生成 AST(抽象語(yǔ)法樹(shù))

          2.生成字節(jié)碼

          然后解釋器根據(jù)字節(jié)碼來(lái)執(zhí)行程序。但 JS 整個(gè)執(zhí)行的過(guò)程其實(shí)會(huì)比這個(gè)更加復(fù)雜,接下來(lái)就來(lái)一一地拆解。

          1.生成 AST

          生成 AST 分為兩步——詞法分析和語(yǔ)法分析。

          詞法分析即分詞,它的工作就是將一行行的代碼分解成一個(gè)個(gè)token。 比如下面一行代碼:

          let name='sanyuan'

          其中會(huì)把句子分解成四個(gè)部分:



          即解析成了四個(gè)token,這就是詞法分析的作用。

          接下來(lái)語(yǔ)法分析階段,將生成的這些 token 數(shù)據(jù),根據(jù)一定的語(yǔ)法規(guī)則轉(zhuǎn)化為AST。舉個(gè)例子:

          let name='sanyuan'
          console.log(name)

          最后生成的 AST 是這樣的:



          當(dāng)生成了 AST 之后,編譯器/解釋器后續(xù)的工作都要依靠 AST 而不是源代碼。順便補(bǔ)充一句,babel 的工作原理就是將 ES6 的代碼解析生成ES6的AST,然后將 ES6 的 AST 轉(zhuǎn)換為 ES5 的AST,最后才將 ES5 的 AST 轉(zhuǎn)化為具體的 ES5 代碼。

          回到 V8 本身,生成 AST 后,接下來(lái)會(huì)生成執(zhí)行上下文

          2. 生成字節(jié)碼

          開(kāi)頭就已經(jīng)提到過(guò)了,生成 AST 之后,直接通過(guò) V8 的解釋器(也叫Ignition)來(lái)生成字節(jié)碼。但是字節(jié)碼并不能讓機(jī)器直接運(yùn)行,那你可能就會(huì)說(shuō)了,不能執(zhí)行還轉(zhuǎn)成字節(jié)碼干嘛,直接把 AST 轉(zhuǎn)換成機(jī)器碼不就得了,讓機(jī)器直接執(zhí)行。確實(shí),在 V8 的早期是這么做的,但后來(lái)因?yàn)闄C(jī)器碼的體積太大,引發(fā)了嚴(yán)重的內(nèi)存占用問(wèn)題。

          給一張對(duì)比圖讓大家直觀地感受以下三者代碼量的差異:



          很容易得出,字節(jié)碼是比機(jī)器碼輕量得多的代碼。那 V8 為什么要使用字節(jié)碼,字節(jié)碼到底是個(gè)什么東西?

          子節(jié)碼是介于AST 和 機(jī)器碼之間的一種代碼,但是與特定類型的機(jī)器碼無(wú)關(guān),字節(jié)碼需要通過(guò)解釋器將其轉(zhuǎn)換為機(jī)器碼然后執(zhí)行。

          字節(jié)碼仍然需要轉(zhuǎn)換為機(jī)器碼,但和原來(lái)不同的是,現(xiàn)在不用一次性將全部的字節(jié)碼都轉(zhuǎn)換成機(jī)器碼,而是通過(guò)解釋器來(lái)逐行執(zhí)行字節(jié)碼,省去了生成二進(jìn)制文件的操作,這樣就大大降低了內(nèi)存的壓力。

          3. 執(zhí)行代碼

          接下來(lái),就進(jìn)入到字節(jié)碼解釋執(zhí)行的階段啦!

          在執(zhí)行字節(jié)碼的過(guò)程中,如果發(fā)現(xiàn)某一部分代碼重復(fù)出現(xiàn),那么 V8 將它記做熱點(diǎn)代碼(HotSpot),然后將這么代碼編譯成機(jī)器碼保存起來(lái),這個(gè)用來(lái)編譯的工具就是V8的編譯器(也叫做TurboFan) , 因此在這樣的機(jī)制下,代碼執(zhí)行的時(shí)間越久,那么執(zhí)行效率會(huì)越來(lái)越高,因?yàn)橛性絹?lái)越多的字節(jié)碼被標(biāo)記為熱點(diǎn)代碼,遇到它們時(shí)直接執(zhí)行相應(yīng)的機(jī)器碼,不用再次將轉(zhuǎn)換為機(jī)器碼。

          其實(shí)當(dāng)你聽(tīng)到有人說(shuō) JS 就是一門解釋器語(yǔ)言的時(shí)候,其實(shí)這個(gè)說(shuō)法是有問(wèn)題的。因?yàn)樽止?jié)碼不僅配合了解釋器,而且還和編譯器打交道,所以 JS 并不是完全的解釋型語(yǔ)言。而編譯器和解釋器的 根本區(qū)別在于前者會(huì)編譯生成二進(jìn)制文件但后者不會(huì)。

          并且,這種字節(jié)碼跟編譯器和解釋器結(jié)合的技術(shù),我們稱之為即時(shí)編譯, 也就是我們經(jīng)常聽(tīng)到的JIT。

          這就是 V8 中執(zhí)行一段JS代碼的整個(gè)過(guò)程,梳理一下:

          1. 首先通過(guò)詞法分析和語(yǔ)法分析生成 AST
          2. 將 AST 轉(zhuǎn)換為字節(jié)碼
          3. 由解釋器逐行執(zhí)行字節(jié)碼,遇到熱點(diǎn)代碼啟動(dòng)編譯器進(jìn)行編譯,生成對(duì)應(yīng)的機(jī)器碼, 以優(yōu)化執(zhí)行效率。

          javascript 是一門單線程的語(yǔ)言,在同一個(gè)時(shí)間只能做完成一件任務(wù),如果有多個(gè)任務(wù),就必須排隊(duì),前面一個(gè)任務(wù)完成,再去執(zhí)行后面的任務(wù)。作為瀏覽器端的腳本語(yǔ)言,javascript 的主要功能是用來(lái)和用戶交互以及操作 dom。假設(shè) javascript 不是單線程語(yǔ)言,在一個(gè)線程里我們給某個(gè) dom 節(jié)點(diǎn)增加內(nèi)容的時(shí)候,另一個(gè)線程同時(shí)正在刪除這個(gè) dom 節(jié)點(diǎn)的內(nèi)容,則會(huì)造成混亂。

          由于 js 單線程的設(shè)計(jì),假設(shè) js 程序的執(zhí)行都是同步。如果執(zhí)行一些耗時(shí)較長(zhǎng)的程序,例如 ajax 請(qǐng)求,在請(qǐng)求開(kāi)始至請(qǐng)求響應(yīng)的這段時(shí)間內(nèi),當(dāng)前的工作線程一直是空閑狀態(tài), ajax 請(qǐng)求后面的 js 代碼只能等待請(qǐng)求結(jié)束后執(zhí)行,因此會(huì)導(dǎo)致 js 阻塞的問(wèn)題。

          javascript 單線程指的是瀏覽器中負(fù)責(zé)解釋和執(zhí)行 javascript 代碼的只有一個(gè)線程,即為 js 引擎線程,但是瀏覽器的渲染進(jìn)程是提供多個(gè)線程的,如下:

          1. js 引擎線程
          2. 事件觸發(fā)線程
          3. 定時(shí)器觸發(fā)線程
          4. 異步 http 請(qǐng)求線程
          5. GUI 渲染線程

          一、異步 & 同步

          為解決上述類似上述 js 阻塞的問(wèn)題,js 引入了同步和異步的概念。

          1、什么是同步?

          “同步”就是后一個(gè)任務(wù)等待前一個(gè)任務(wù)結(jié)束后再去執(zhí)行。

          2、什么是異步?

          “異步”與同步不同,每一個(gè)異步任務(wù)都有一個(gè)或多個(gè)回調(diào)函數(shù)。webapi 會(huì)在其相應(yīng)的時(shí)機(jī)里將回調(diào)函數(shù)添加進(jìn)入消息隊(duì)列中,不直接執(zhí)行,然后再去執(zhí)行后面的任務(wù)。直至當(dāng)前同步任務(wù)執(zhí)行完畢后,再把消息隊(duì)列中的消息添加進(jìn)入執(zhí)行棧進(jìn)行執(zhí)行。

          異步任務(wù)在瀏覽器中一般是以下:

          1. 網(wǎng)絡(luò)請(qǐng)求
          2. 計(jì)時(shí)器
          3. DOM 監(jiān)聽(tīng)事件
          4. ...

          二、什么是執(zhí)行棧(stack)、堆(heap)、事件隊(duì)列(task queue)?

          1、執(zhí)行棧

          “棧”是一種數(shù)據(jù)結(jié)構(gòu),是一種線性表。特點(diǎn)為 LIFO,即先進(jìn)后出 (last in, first out)。

          利用數(shù)組的 push 和 shift 可以實(shí)現(xiàn)壓棧和出棧的操作。

          在代碼運(yùn)行的過(guò)程中,函數(shù)的調(diào)用會(huì)形成一個(gè)由若干幀組成的棧。

          function foo(b) {
            let a=10;
            return a + b + 11;
          }
          
          function bar(x) {
            let y=3;
            return foo(x * y);
          }
          
          console.log(bar(7))

          上面代碼最終會(huì)在控制臺(tái)打印42,下面梳理一下它的執(zhí)行順序。

          1. console.log 函數(shù)作為第一幀壓入棧中。
          2. 調(diào)用 bar,第二幀被壓入棧中。幀中包含著 bar 的變量對(duì)象。
          3. bar 調(diào)用 foo,foo 做一位第三幀被壓入棧中,幀中包含著 foo 的變量對(duì)象。
          4. foo 執(zhí)行完畢然后返回。被彈出棧。
          5. bar 執(zhí)行完畢然后返回,被彈出棧。
          6. log 函數(shù)接收到 bar 的返回值。執(zhí)行完畢后,出棧。此時(shí)棧已空。

          2、堆

          對(duì)象被分配在堆中,堆是一個(gè)用來(lái)表示一大塊(通常是非結(jié)構(gòu)化的)內(nèi)存區(qū)域的計(jì)算機(jī)術(shù)語(yǔ)。

          堆和棧的區(qū)別

          首先,stack 是有結(jié)構(gòu)的,每個(gè)區(qū)塊按照一定次序存放,可以明確知道每個(gè)區(qū)塊的大小;heap 是沒(méi)有結(jié)構(gòu)的,數(shù)據(jù)可以任意存放。因此,

          stack 的尋址速度要快于 heap。

          其次,每個(gè)線程分配一個(gè) stack,每個(gè)進(jìn)程分配一個(gè) heap,也就是說(shuō),stack 是線程獨(dú)占的,heap 是線程共用的。

          此外,stack 創(chuàng)建的時(shí)候,大小是確定的,數(shù)據(jù)從超過(guò)這個(gè)大小,就發(fā)生 stack overflow 錯(cuò)誤,而 heap 的大小是不確定的,

          需要的話可以不斷增加。

          public void Method1()
          {
              int i=4;
          
              int y=2;
          
              class1 cls1=new class1();
          }

          上面代碼這三個(gè)變量和一個(gè)對(duì)象實(shí)例在內(nèi)存中的存放方式如下。

          從上圖可以看到,i、y和cls1都存放在stack,因?yàn)樗鼈冋加脙?nèi)存空間都是確定的,而且本身也屬于局部變量。但是,cls1指向的對(duì)象實(shí)例存放在heap,因?yàn)樗拇笮〔淮_定。作為一條規(guī)則可以記住,所有的對(duì)象都存放在heap。

          接下來(lái)的問(wèn)題是,當(dāng)Method1方法運(yùn)行結(jié)束,會(huì)發(fā)生什么事?

          回答是整個(gè)stack被清空,i、y和cls1這三個(gè)變量消失,因?yàn)樗鼈兪蔷植孔兞浚瑓^(qū)塊一旦運(yùn)行結(jié)束,就沒(méi)必要再存在了。而heap之中的那個(gè)對(duì)象實(shí)例繼續(xù)存在,直到系統(tǒng)的垃圾清理機(jī)制(garbage collector)將這塊內(nèi)存回收。因此,一般來(lái)說(shuō),內(nèi)存泄漏都發(fā)生在heap,即某些內(nèi)存空間不再被使用了,卻因?yàn)榉N種原因,沒(méi)有被系統(tǒng)回收。

          3、事件隊(duì)列和事件循環(huán)

          隊(duì)列是一種數(shù)據(jù)結(jié)構(gòu),也是一種特殊的線性表。特點(diǎn)為 FIFO,即先進(jìn)先出(first in, first out)

          利用數(shù)組的 push 和 pop 可實(shí)現(xiàn)入隊(duì)和出隊(duì)的操作。

          事件循環(huán)和事件隊(duì)列的維護(hù)是由事件觸發(fā)線程控制的。

          事件觸發(fā)線程線程同樣是由瀏覽器渲染引擎提供的,它會(huì)維護(hù)一個(gè)事件隊(duì)列。

          js 引擎遇到上文所列的異步任務(wù)后,會(huì)交個(gè)相應(yīng)的線程去維護(hù)異步任務(wù),等待某個(gè)時(shí)機(jī),然后由事件觸發(fā)線程將異步任務(wù)對(duì)應(yīng)的回調(diào)函數(shù)加入到事件隊(duì)列中,事件隊(duì)列中的函數(shù)等待被執(zhí)行。

          js 引擎在執(zhí)行過(guò)程中,遇到同步任務(wù),會(huì)將任務(wù)直接壓入執(zhí)行棧中執(zhí)行,當(dāng)執(zhí)行棧為空(即 js 引擎線程空閑), 事件觸發(fā)線程 會(huì)從事件隊(duì)列中取出一個(gè)任務(wù)(即異步任務(wù)的回調(diào)函數(shù))放入執(zhí)行在棧中執(zhí)行。

          執(zhí)行完了之后,執(zhí)行棧再次為空,事件觸發(fā)線程會(huì)重復(fù)上一步的操作,再?gòu)氖录?duì)列中取出一個(gè)消息,這種機(jī)制就被稱為 事件循環(huán) (Event Loop)機(jī)制。

          為了更好地理解Event Loop,請(qǐng)看下圖(轉(zhuǎn)引自Philip Roberts的演講《Help, I'm stuck in an event-loop》)。

          例子代碼:

          console.log('script start')
          
          setTimeout(()=> {
            console.log('timer 1 over')
          }, 1000)
          
          setTimeout(()=> {
            console.log('timer 2 over')
          }, 0)
          
          console.log('script end')
          
          // script start
          // script end
          // timer 2 over
          // timer 1 over

          模擬 js 引擎對(duì)其執(zhí)行過(guò)程:

          第一輪事件循環(huán):

          1. console.log 為同步任務(wù),入棧,打印“script start”。出棧。
          2. setTimeout 為異步任務(wù),入棧,交給定時(shí)器觸發(fā)線程處理(在1秒后加入將回調(diào)加入事件隊(duì)列)。出棧。
          3. setTimeout 為異步任務(wù),入棧,交給定時(shí)器觸發(fā)線程處理(在4ms之內(nèi)將回調(diào)加入事件隊(duì)列)。出棧。
          4. console.log 為同步任務(wù),入棧,打印"script end"。出棧。

          此時(shí),執(zhí)行棧為空,js 引擎線程空閑。便從事件隊(duì)列中讀取任務(wù),此時(shí)隊(duì)列如下:

          第二輪事件循環(huán)

          1. js 引擎線程從事件隊(duì)列中讀取 cb2 加入執(zhí)行棧并執(zhí)行,打印”time 2 over“。出棧。

          第三輪事件循環(huán)

          1. js 引擎從事件隊(duì)列中讀取 cb1 加入執(zhí)行棧中并執(zhí)行,打印”time 1 over“ 。出棧。

          注意點(diǎn):

          上面,timer 2 的延時(shí)為 0ms,HTML5標(biāo)準(zhǔn)規(guī)定 setTimeout 第二個(gè)參數(shù)不得小于4(不同瀏覽器最小值會(huì)不一樣),不足會(huì)自動(dòng)增加,所以 "timer 2 over" 還是會(huì)在 "script end" 之后。

          就算延時(shí)為0ms,只是 time 2 的回調(diào)函數(shù)會(huì)立即加入事件隊(duì)列而已,回調(diào)的執(zhí)行還是得等到執(zhí)行棧為空時(shí)執(zhí)行。

          四、宏任務(wù) & 微任務(wù)

          在 ES6 新增 Promise 處理異步后,js 執(zhí)行引擎的處理過(guò)程又發(fā)生了新的變化。

          看代碼:

          console.log('script start')
          
          setTimeout(function() {
              console.log('timer over')
          }, 0)
          
          Promise.resolve().then(function() {
              console.log('promise1')
          }).then(function() {
              console.log('promise2')
          })
          
          console.log('script end')
          
          // script start
          // script end
          // promise1
          // promise2
          // timer over

          這里又新增了兩個(gè)新的概念, macrotask (宏任務(wù))和 microtask (微任務(wù))。

          所有的任務(wù)都劃分到宏任務(wù)和微任務(wù)下:

          • macrotask : script 主代碼塊、setTimeout、setInterval、requestAnimationFrame、node 中的setimmediate 等。
          • microtask : Promise.then catch finally、MutationObserver、node 中的process.nextTick 等。

          js 引擎首先執(zhí)行主代碼塊。

          執(zhí)行棧每次執(zhí)行的代碼就是一個(gè)宏任務(wù),包括任務(wù)隊(duì)列(宏任務(wù)隊(duì)列)中的。執(zhí)行棧中的任務(wù)執(zhí)行完畢后,js 引擎會(huì)從宏任務(wù)隊(duì)列中去添加任務(wù)到執(zhí)行棧中,即同樣是事件循環(huán)的機(jī)制。

          當(dāng)在執(zhí)行宏任務(wù)遇到微任務(wù) Promise.then 時(shí),會(huì)創(chuàng)建一個(gè)微任務(wù),并加入到微任務(wù)隊(duì)列中的隊(duì)尾。

          微任務(wù)是在宏任務(wù)執(zhí)行的時(shí)候創(chuàng)建的,而在下一個(gè)宏任務(wù)執(zhí)行之前,瀏覽器會(huì)對(duì)頁(yè)面重新渲染(task >> render >> task(任務(wù)隊(duì)列中讀取))。 同時(shí),在上一個(gè)宏任務(wù)執(zhí)行完成后,頁(yè)面渲染之前,會(huì)執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)。

          所以上述代碼的執(zhí)行過(guò)程就可以解釋了。

          js 引擎執(zhí)行 promise.then 時(shí),promise1、promise2 被認(rèn)為是兩個(gè)微任務(wù)按照代碼的先后順序被加入到微任務(wù)隊(duì)列中,script end執(zhí)行后,空。

          此時(shí)當(dāng)前宏任務(wù)(script 主代碼塊)執(zhí)行完畢,并不從當(dāng)前宏任務(wù)隊(duì)列中讀取任務(wù)。而是立馬清空當(dāng)前宏任務(wù)所產(chǎn)生的微任務(wù)隊(duì)列。將兩個(gè)微任務(wù)依次放入執(zhí)行棧中執(zhí)行。執(zhí)行完畢,打印 promise1、promise2。棧空。 此時(shí),第一輪事件循環(huán)結(jié)束。

          緊接著,再去讀取宏任務(wù)隊(duì)列中的任務(wù),time over 被打印。棧空。

          因此,宏任務(wù)和微任務(wù)的執(zhí)行機(jī)制如下:

          1. 執(zhí)行一個(gè)宏任務(wù)(棧中沒(méi)有就從宏任務(wù)隊(duì)列中獲取)
          2. 執(zhí)行過(guò)程中遇到微任務(wù),就將它添加到微任務(wù)的任務(wù)隊(duì)列中
          3. 宏任務(wù)執(zhí)行完畢,立即執(zhí)行當(dāng)前微任務(wù)隊(duì)列中的所有微任務(wù)(依次執(zhí)行)
          4. 當(dāng)前所有微任務(wù)執(zhí)行完畢后,開(kāi)始檢查渲染,GUI 線程接管渲染
          5. 渲染完畢后,JS 引擎繼續(xù)開(kāi)始下一個(gè)宏任務(wù),從宏任務(wù)隊(duì)列中獲取

          async & await

          因?yàn)?async 和 await 本質(zhì)上還是基于 Promise 的封裝,而 Promise 是屬于微任務(wù)的一種。所以使用 await 關(guān)鍵字與 Promise.then 效果類似:

          setTimeout(_=> console.log(4))
          
          async function main() {
            console.log(1)
            await Promise.resolve()
            console.log(3)
          }
          
          main()
          
          console.log(2)
          // 1
          // 2
          // 3
          // 4

          async 函數(shù)在 await 之前的代碼都是同步執(zhí)行的, 可以理解為 await 之前的代碼都屬于 new Promise 時(shí)傳入的代碼,await 之后的所有代碼都是 Promise.then 中的回調(diào),即在微任務(wù)隊(duì)列中。

          五、總結(jié)

          1. js 單線程實(shí)際上時(shí)解釋執(zhí)行 js 代碼的只有一個(gè)線程,但是瀏覽器的渲染是多線程的。
          2. 異步和同步的概念與區(qū)別,異步任務(wù)有哪些。
          3. 棧、堆、隊(duì)列的特點(diǎn)和使用場(chǎng)景。
          4. 事件隊(duì)列以及事件循環(huán)機(jī)制。
          5. es6 下,宏任務(wù)與微任務(wù)的執(zhí)行過(guò)程。

          參考:

          • JavaScript 異步與事件循環(huán)
          • 并發(fā)模型與事件循環(huán)
          • 微任務(wù)、宏任務(wù)與Event-Loop
          • JavaScript 運(yùn)行機(jī)制詳解:再談Event Loop
          • JS事件循環(huán)
          • [譯] 深入理解 JavaScript 事件循環(huán)(二)— task and microtask
          • Help, I'm stuck in an event-loop

          原文作者:大芒果哇

          原文地址:https://www.cnblogs.com/shenggao/p/13799566.html


          主站蜘蛛池模板: 精品一区二区三区无码免费直播| 成人精品一区二区电影| 日韩成人一区ftp在线播放| 国产一区二区三区不卡在线看| 色国产在线视频一区| 大帝AV在线一区二区三区| 日本一区二区三区精品国产| 国产日韩一区二区三区在线观看| 精品国产一区二区三区www| 日本精品少妇一区二区三区| 久久久国产一区二区三区| 亚洲一区二区三区播放在线| 国产综合精品一区二区| 精品日产一区二区三区手机| 日韩精品一区二区三区中文版| 中文国产成人精品久久一区| 国产精品视频一区二区三区经| 国偷自产Av一区二区三区吞精| 亚洲AV日韩AV天堂一区二区三区 | 国产精久久一区二区三区| 久久综合精品不卡一区二区| 亚洲熟女乱综合一区二区| 日韩有码一区二区| 一区二区三区中文字幕| 精品黑人一区二区三区| 亚洲国产精品乱码一区二区| 东京热无码av一区二区| 国产日韩一区二区三区在线观看| 亚洲一区在线免费观看| 国产精品乱码一区二区三区| 无码少妇一区二区浪潮av| 日本精品一区二区三区在线视频一 | 色多多免费视频观看区一区| 国产一区二区三区手机在线观看| 久久久综合亚洲色一区二区三区 | 国产一区二区三区久久精品| 国产日韩精品一区二区三区在线| 99国产精品一区二区| 无码日韩精品一区二区免费暖暖| 国产经典一区二区三区蜜芽| 久久久久人妻一区精品性色av|