日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

stm32怎么调用for循环内部的变量_循环中的异步amp;amp;循环中的闭包

發布時間:2023/12/15 编程问答 21 豆豆
生活随笔 收集整理的這篇文章主要介紹了 stm32怎么调用for循环内部的变量_循环中的异步amp;amp;循环中的闭包 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在這之前先要了解一下

for循環中let 和var的區別

var 是函數級作用域或者全局作用域,let是塊級作用域 看一個例子

????function?foo()?{

??????for?(var?index =?0; index < array.length; index++) {

????????//..循環中的邏輯代碼

??????}

??????console.log(index);//=>5

????}

????foo()

???console.log(index)//Uncaught ReferenceError: index is not defined

foo函數下的index輸出5,全局下的index不存在

現在我們把var 換為let

????function?foo()?{

??????for?(let?index =?0; index < array.length; index++) {

????????//..循環中的邏輯代碼

??????}

??????console.log(index)//Uncaught ReferenceError: index is not defined

????}

????foo()

報錯了,index不在foo函數作用域下,當然肯定也不會再全局下

因為var和let的這個區別(當然var和let的區別不止于此)所以導致了下面的這個問題

關于var

????const?array = [1,?2,?3,?4,?5]

????function?foo()?{

??????for?(var?index =?0; index < array.length; index++) {

????????setTimeout(()?=>?{

??????????console.log(index);

????????},?1000);

??????}

????}

????foo()

看下輸出

關于let的

????const?array = [1,?2,?3,?4,?5]

????function?foo()?{

??????for?(let?index =?0; index < array.length; index++) {

????????setTimeout(()?=>?{

??????????console.log(index);

????????},?1000);

??????}

????}

????foo()

看下輸出

因為var和let 在作用域上的差別,所以到這了上面的問題

使用var 定義變量的時候,作用域是在foo函數下,在for循環外部,在整個循環中是全局的,每一次的循環實際上是為index賦值,循環一次賦值一次,5次循環完成,index最后的結果賦值就為5;就是被最終賦值的index,就是5;

let的作用局的塊級作用局,index的作用域在for循環內部,即每次循環的index的作用域就是本次循環,下一次循環重新定義變量index;所以index每次循環的輸出都不同

這里還有另外一個問題,setTimeout,這是一個異步,這就是我們今天要討論的

循環中的異步

setTimeout(func,time)函數運行機制

setTimeout(func,time)是在time(毫秒單位)時間后執行func函數。瀏覽器引擎按順序執行程序,遇到setTimeout會將func函數放到執行隊列中,等到主程序執行完畢之后,才開始從執行隊列(隊列中可能有多個待執行的func函數)中按照time延時時間的先后順序取出來func并執行。即使time=0,也會等主程序運行完之后,才會執行。

一個需求,一個數組array[1,2,3,4,5],循環打印,間隔1秒

上面的let是循環打印了12345,但是不是間隔1s打印的,是在foo函數執行1s后,同時打印的

方式一, 放棄for循環,使用setInterval

????function?foo(){

??????let?index =?0;

??????const?array = [1,?2,?3,?4,?5]

??????const?t = setInterval(()=>{

????????if?(index < array.length) {

??????????console.log(array[index]);

????????}

????????index++;

??????},?1000);

??????if?(index >= array.length) {

????????clearInterval(t);

??????}

????}

????foo()

我們上面說到,當for循環遇到了var,變量index的作用域在foo函數下,循環一次賦值一次,5次循環完成,index最后的結果賦值就為5;就是被最終賦值的index,就是5;

方式二,引入全局變量

代碼執行順序是,先同步執行for循環,再執行異步隊列,在for循環執行完畢后,異步隊列開始執行之前,index經過for循環的處理,變成了5。

所以我們引入一個全局變量j,使j在for循環執行完畢后,異步隊列開始執行之前,依然是0,在異步執行時進行累加

????var?j =?0;

????for?(var?index =?0; index < array.length; index++) {

??????setTimeout(()?=>?{

????????console.log(j);

????????j++;

??????},?1000?* index)

????}

方式三, for循環配合setTimeout(常規思路,不贅述,面試必備技能)

????const?array = [1,?2,?3,?4,?5]

????function?foo()?{

??????for?(let?index =?0; index < array.length; index++) {

????????setTimeout(()?=>?{

??????????console.log(index);

????????},?1000*index);

??????}

????}

????foo()

方式四,通過閉包實現

開始討論方式四之前我推薦先閱讀一遍我之前寫過一篇文章

談一談javascript作用域

我們對上面的問題再次分析,for循環同步執行,在for循環內部遇到了setTimeout,setTimeout是異步執行的,所以加入了異步隊列,當同步的for循環執行完畢后,再去執行異步隊列,setTimeout中有唯一的一個參數數index

方式三可行,是因為let是塊級作用域,每次for執行都會創建新的變量index,for循環執行完畢后,異步執行之前,創建了5個獨立的作用域,5個index變量,分別是0,1,2,3,4,相互獨立,互不影響,輸出了預期的結果

如果說每次循環都會生成一個獨立的作用域用來保存index,問題就會得到解決,所以,我們通過閉包來實現

????const?array = [1,?2,?3,?4,?5]

????function?foo()?{

??????for?(var?index =?0; index < array.length; index++) {

????????function?fun(j)?{

??????????setTimeout(function?()?{

????????????console.log(j);

??????????},?1000?* j);

????????}

????????fun(index)

??????}

????}

????foo()

setTimeout中的匿名回調函數中引用了函數fun中的局部變量j,所以當fun執行完畢后,變量j不會被釋放,這就形成了閉包

當然我們可以對此進行一下優化

????const?array = [1,?2,?3,?4,?5]

????function?foo()?{

??????for?(var?index =?0; index < array.length; index++) {

????????(function(j)?{

??????????setTimeout(function?()?{

????????????console.log(j);

??????????},?1000?* j);

????????})(index)

??????}

????}

????foo()

將foo函數改為匿名的立即執行函數,結果是相同的

總結

for循環本身是同步執行的,當在for循環中遇到了異步邏輯,異步就會進入異步隊列,當for循環執行結束后,才會執行異步隊列 當異步函數依賴于for循環中的索引時(一定是存在依賴關系的,不然不會再循環中調動異步函數)要考慮作用域的問題,

在ES6中使用let是最佳的選擇

當使用var時,可以考慮再引入一個索引來替代for循環中的索引,新的索引邏輯要在異步中處理

也可以使用閉包,模擬實現let 在實際開發過程中,循環調用異步函數,比demo要復雜,可能還會出現if和else判斷等邏輯,具體的我們下次再續

總結

以上是生活随笔為你收集整理的stm32怎么调用for循环内部的变量_循环中的异步amp;amp;循环中的闭包的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。