摘要:修改下面代碼,使其能夠正確運行為什么上面代碼的執(zhí)行結果是首先說明,這與異步和作用域都有關系。先來說和異步的關系,是異步操作,所謂的異步就是會在同步操作全部執(zhí)行完成之后,才開始執(zhí)行的。
// 修改下面代碼,使其能夠正確運行 for(var i = 0; i < 6; i++) { setTimeout(function timer(){ console.log(i) }, i * 1000) }
為什么上面代碼的執(zhí)行結果是 [6,6,6,6,6,6] ?
首先說明,這與異步和作用域都有關系。
先來說和異步的關系,setTimeout是異步操作,所謂的異步就是會在同步操作全部執(zhí)行完成之后,才開始執(zhí)行的。放在上面的代碼中解釋就是,setTimeout是在每次for循環(huán)的時候都會調(diào)用的(用于將setTimeout內(nèi)部的代碼放入隊列,在同步代碼執(zhí)行完成之后,再根據(jù)定時執(zhí)行),但是setTimeout中的代碼是在for循環(huán)結束之后才開始執(zhí)行的,所以當for循環(huán)執(zhí)行完成的時候,i變成了6,那么timer中對i的引用也變成了6。
然后是和作用域的關系,for循環(huán)中定義的變量i ,它的作用域是什么?
for(var i = 0; i<6; i++) ----> var i = 0; for(i; i<6; i++)
是 window,所以當for循環(huán)執(zhí)行完成的時候,全局變量i的值為6,此時去執(zhí)行隊列中的timer函數(shù),但是timer中并沒有定義i,所以就會沿著作用域鏈向外層查找,就找到了window中的全局變量i,值為6。
// 第一種方法:使用立即執(zhí)行函 for(var i = 0; i < 6; i++) { (function(j){ setTimeout(function timer(){ console.log(j) }, j * 1000) })(i) } // 第二種方法:使用let關鍵字 for(let i = 0; i < 6; i++) { setTimeout(function timer(){ console.log(i) }, i * 1000) }
這兩種方法的本質(zhì)其實是一樣的,都是創(chuàng)建了一個新的變量去保存for循環(huán)中每次變化的i的值,再將其傳遞給timer,使timer每次在執(zhí)行的時候都能得到正確的值。在使用let的時候,可以看到babel將其轉(zhuǎn)譯之后的結果,使用了一個新的參數(shù)來保存每次循環(huán)時的i,所以在6次循環(huán)中,會開辟出6個內(nèi)存空間,保存著6個不同的i ,這樣的話,setTimeout中對i的引用就能得到正確的值。
文章版權歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/99503.html
摘要:同步異步回調(diào)傻傻分不清楚。分割線上面主要講了同步和回調(diào)執(zhí)行順序的問題,接著我就舉一個包含同步異步回調(diào)的例子。同步優(yōu)先回調(diào)內(nèi)部有個,第二個是一個回調(diào)回調(diào)墊底。異步也,輪到回調(diào)的孩子們回調(diào),出來執(zhí)行了。 同步、異步、回調(diào)?傻傻分不清楚。 大家注意了,教大家一道口訣: 同步優(yōu)先、異步靠邊、回調(diào)墊底(讀起來不順) 用公式表達就是: 同步 => 異步 => 回調(diào) 這口訣有什么用呢?用來對付面試的...
摘要:同步異步回調(diào)傻傻分不清楚。分割線上面主要講了同步和回調(diào)執(zhí)行順序的問題,接著我就舉一個包含同步異步回調(diào)的例子。同步優(yōu)先回調(diào)內(nèi)部有個,第二個是一個回調(diào)回調(diào)墊底。異步也,輪到回調(diào)的孩子們回調(diào),出來執(zhí)行了。 同步、異步、回調(diào)?傻傻分不清楚。 大家注意了,教大家一道口訣: 同步優(yōu)先、異步靠邊、回調(diào)墊底(讀起來不順) 用公式表達就是: 同步 => 異步 => 回調(diào) 這口訣有什么用呢?用來對付面試的...
摘要:瀏覽器是多進程的,而瀏覽器的內(nèi)核渲染進程是多線程的。如果已經(jīng)將回調(diào)函數(shù)放進任務隊列,但是主線程正在執(zhí)行一個非常耗時的任務,當這個任務執(zhí)行完畢后,主線程去任務隊列中取任務,這個時候,就會出現(xiàn)連續(xù)執(zhí)行的情況,也就是說相當于失效了。 前言 ??在刷筆試題的時候,經(jīng)常會碰到setTimeout的問題,只知道這個是設置定時器;但是考察的重點一般是在一個方法中包含了定時器,定時器中的打印和方法中打...
摘要:注意如果主邏輯的代碼執(zhí)行時間已經(jīng)超過了第二個參數(shù)設置的時間,那么等運行到該回調(diào)函數(shù)時,它會忽略掉這個時間,并立即執(zhí)行。如果某一個進行大量的計算,那么它就會阻塞在當前的回調(diào)函數(shù)中,等待該計算完成后,再執(zhí)行下一個的回調(diào)函數(shù)。 setTimeout() ? JavaScript是一個單線程的語言,也就是說它同一時間只能執(zhí)行一段代碼,接下來我們通過兩個例子說明一下單線程語言和多線程語言的...
閱讀 2002·2023-04-25 16:19
閱讀 3116·2021-11-24 09:39
閱讀 837·2021-11-16 11:44
閱讀 1699·2019-08-29 12:52
閱讀 1147·2019-08-26 13:33
閱讀 1081·2019-08-26 10:26
閱讀 2209·2019-08-23 16:42
閱讀 2574·2019-08-23 14:37