91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

setTimeout與循環閉包的示例分析

發布時間:2021-09-17 09:10:45 來源:億速云 閱讀:126 作者:柒染 欄目:web開發

這期內容當中小編將會給大家帶來有關setTimeout與循環閉包的示例分析,文章內容豐富且以專業的角度為大家分析和敘述,閱讀完這篇文章希望大家可以有所收獲。

setTimeout與循環閉包的示例分析

我在詳細圖解作用域鏈與閉包一文中的結尾留下了一個關于setTimeout與循環閉包的思考題。

利用閉包,修改下面的代碼,讓循環輸出的結果依次為1, 2, 3, 4, 5

for (var i=1; i<=5; i++) {     setTimeout( function timer() {         console.log(i);     }, i*1000 ); }

值得高興的是很多朋友在讀了文章之后確實對閉包有了更加深刻的了解,并準確的給出了幾種寫法。一些朋友能夠認真的閱讀我的文章并且一個例子一個例子的上手練習,這種認可對我而言真的非常感動。但是也有一些基礎稍差的朋友在閱讀了之后,對于這題的理解仍然感到困惑,因此應一些讀者老爺的要求,借此文章專門對setTimeout進行一個相關的知識分享,愿大家讀完之后都能夠有新的收獲。

在最初學習setTimeout的時候,我們很容易知道setTimeout有兩個參數,***個參數為一個函數,我們通過該函數定義將要執行的操作。第二個參數為一個時間毫秒數,表示延遲執行的時間。

setTimeout(function() {     console.log('一秒鐘之后我將被打印出來') }, 1000)

setTimeout與循環閉包的示例分析

上例執行結果

可能不少人對于setTimeout的理解止步于此,但還是有不少人發現了一些其他的東西,并在評論里提出了疑問。比如上圖中的這個數字7,是什么?

每一個setTimeout在執行時,會返回一個***ID,上圖中的數字7,就是這個***ID。我們在使用時,常常會使用一個變量將這個***ID保存起來,用以傳入clearTimeout,清除定時器。

var timer = setTimeout(function() {  console.log('如果不清除我,我將會一秒之后出現。');  }, 1000)  clearTimeout(timer); // 清除之后,通過setTimeout定義的操作并不會執行

接下來,我們還需要考慮另外一個重要的問題,那就是setTimeout中定義的操作,在什么時候執行?為了引起大家的重視,我們來看看下面的例子。

var timer = setTimeout(function() {  console.log('setTimeout actions.');  }, 0);  console.log('other actions.');  // 思考一下,當我將setTimeout的延遲時間設置為0時,上面的執行順序會是什么?

在瀏覽器中的console中運行試試看,很容易就能夠知道答案,如果你沒有猜中答案,那么我這篇文章就值得你點一個贊了,因為接下來我分享的小知識,可能會在筆試中救你一命。

在對于執行上下文的介紹中,我與大家分享了函數調用棧這種特殊數據結構的調用特性。在這里,將會介紹另外一個特殊的隊列結構,頁面中所有由setTimeout定義的操作,都將放在同一個隊列中依次執行。

我用下圖跟大家展示一下隊列數據結構的特點。

setTimeout與循環閉包的示例分析

隊列:先進先出

而這個隊列執行的時間,需要等待到函數調用棧清空之后才開始執行。即所有可執行代碼執行完畢之后,才會開始執行由setTimeout定義的操作。而這些操作進入隊列的順序,則由設定的延遲時間來決定。

因此在上面這個例子中,即使我們將延遲時間設置為0,它定義的操作仍然需要等待所有代碼執行完畢之后才開始執行。這里的延遲時間,并非相對于setTimeout執行這一刻,而是相對于其他代碼執行完畢這一刻。所以上面的例子執行結果就非常容易理解了。

為了幫助大家理解,再來一個結合變量提升的更加復雜的例子。如果你能夠正確看出執行順序,那么你對于函數的執行就有了比較正確的認識了,如果還不能,就回過頭去看看其他幾篇文章。

setTimeout(function() {     console.log(a); }, 0);   var a = 10;   console.log(b); console.log(fn);   var b = 20;   function fn() {     setTimeout(function() {         console.log('setTImeout 10ms.');     }, 10); }   fn.toString = function() {     return 30; }   console.log(fn);   setTimeout(function() {     console.log('setTimeout 20ms.'); }, 20);   fn();

setTimeout與循環閉包的示例分析

上栗執行結果

OK,關于setTimeout就暫時先介紹到這里,我們回過頭來看看那個循環閉包的思考題。

for (var i=1; i<=5; i++) {     setTimeout( function timer() {         console.log(i);     }, i*1000 ); }

如果我們直接這樣寫,根據setTimeout定義的操作在函數調用棧清空之后才會執行的特點,for循環里定義了5個setTimeout操作。而當這些操作開始執行時,for循環的i值,已經先一步變成了6。因此輸出結果總為6。而我們想要讓輸出結果依次執行,我們就必須借助閉包的特性,每次循環時,將i值保存在一個閉包中,當setTimeout中定義的操作執行時,則訪問對應閉包保存的i值即可。

而我們知道在函數中閉包判定的準則,即執行時是否在內部定義的函數中訪問了上層作用域的變量。因此我們需要包裹一層自執行函數為閉包的形成提供條件。

因此,我們只需要2個操作就可以完成題目需求,一是使用自執行函數提供閉包條件,二是傳入i值并保存在閉包中。

for (var i=1; i<=5; i++) {       (function(i) {         setTimeout( function timer() {             console.log(i);         }, i*1000 );     })(i) }

setTimeout與循環閉包的示例分析

利用斷點調試,在chrome中查看執行順序與每一個閉包中不同的i值

當然,也可以在setTimeout的***個參數處利用閉包。

for (var i=1; i<=5; i++) {     setTimeout( (function(i) {         return function() {             console.log(i);         }     })(i), i*1000 ); }

上述就是小編為大家分享的setTimeout與循環閉包的示例分析了,如果剛好有類似的疑惑,不妨參照上述分析進行理解。如果想知道更多相關知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

安远县| 托克逊县| 南雄市| 嵊州市| 斗六市| 鄂伦春自治旗| 滦南县| 黄浦区| 吴江市| 怀远县| 富民县| 秭归县| 开阳县| 进贤县| 玉山县| 临夏市| 桦南县| 溆浦县| 章丘市| 江华| 南丰县| 海原县| 玉环县| 平武县| 黎川县| 永宁县| 新田县| 黔东| 安龙县| 泊头市| 望江县| 司法| 徐州市| 五寨县| 阿拉善左旗| 原阳县| 娄底市| 郎溪县| 天津市| 临高县| 巧家县|