搜尋
首頁web前端js教程深入探索javascript計時器_javascript技巧

javascript單線程

JavaScript的單線程,與它的用途有關。作為瀏覽器腳本語言,JavaScript的主要用途是與使用者互動,以及操作DOM。這決定了它只能是單線程,否則會帶來複雜的同步問題。例如,假定JavaScript同時有兩個線程,一個線程在某個DOM節點上加入內容,另一個線程就刪除了這個節點,這時瀏覽器應該以哪個執行緒為準?所以,為了避免複雜性,從一誕生,JavaScript就是單線程,這已經成了這門語言的核心特徵,未來也不會改變。

隊列任務

單執行緒就意味著,所有任務都需要排隊,前一個任務結束,才會執行後一個任務。如果前一個任務耗時很長,後一個任務就得一直等著。


非同步事件驅動

瀏覽器中許多行為是非同步(Asynchronized)的,例如:滑鼠點擊事件、視窗大小拖曳事件、計時器觸發事件、XMLHttpRequest完成回調等。當一個非同步事件發生的時候,它就會進入事件佇列。瀏覽器有一個內部大消息循環,Event Loop(事件循環),會輪詢大的事件佇列並處理事件。例如,瀏覽器目前正忙於處理onclick事件,這時另外一個事件發生了(如:window onSize),這個非同步事件就被放入事件佇列等待處理,只有前面的處理完畢了,空閒了才會執行這個事件。

Event Loop

JavaScript是單執行緒的,但瀏覽器不是單執行緒的

瀏覽器至少會有以下一些進程

1.瀏覽器 GUI 渲染線程

2.JavaScript 引擎執行緒

3.瀏覽器定時觸發器執行緒

4.瀏覽器事件觸發執行緒

5.瀏覽器 http 非同步請求執行緒

因為 JavaScript 引擎是單執行緒的,所以程式碼都是先壓到佇列,然後由引擎採用先進先出的方式運作。事件處理函數、timer 執行函數也會排到這個佇列中,然後利用一個無窮迴圈,不斷從隊頭取出函數執行,這就是Event Loop。

總結一句話,js是單線程的,但是瀏覽器是多線程的,遇到異步的東西都是由瀏覽器把異步的回調放到Event Loop中,js線程不繁忙的時候,再去讀取Event Loop

定時器原理

定時器的用法

setTimeout(fn, delay)

setInterval(fn, delay)

fn是函數也可以是字串,delay是延遲的時間,單位是毫秒

有以下要注意的

1.fn雖然可以是字串,但是一直都不推薦這麼使用

2.fn裡面的函數如果有this,執行的時候this會指向到window上面去


如果理解好了js單線程和Event loop,定時器的原理也很好理解了

如果設定了定時器,當到了延遲時間,瀏覽器會把延遲執行的事件放到Event loop裡面,當時間到了,如果js線程空閒就會執行了(所以定時器的精度不準啊)


看有文章介紹說setTimeout和setInterval對函數一直輪詢的區別,程式碼如下

複製程式碼 程式碼如下:

        setTimeout(function(){
            setTimeout(arguments.callee,100)   
        },100)
        setInterval(function(){},1000)

文章大概的意思是setTimeout是在回調函數執行後才啟動下一次定時器,所以肯定是有間隔的執行,而setInterval是一直都在執行,如果碰到了js線程一直執行,可能就會在Event loop裡面加多個回呼,當js執行緒不忙的時候,會一下子執行多個

經過測試發現無論在ie,ff,chrome,Opera,Safari下,setInterval都是以一定間隔來的

測試程式碼如下

複製程式碼 程式碼如下:

        setInterval(function(){
            xx.innerHTML=xx.innerHTML 1;
        },100);
       
        for(var i=0;i             xx.offsetWidth
        }

        setTimeout(function(){
            debugger;
        },10)

斷點的時候還是只印出了1個1

定時器的精確度問題

因為js單線程原因,如果遇到繁忙,定時器肯定不準,而且肯定是越來越長的,這個好像無解啊,無解啊

還有一個精確度問題就是最小間隔setTimeout(fun,0)

在js執行緒不忙的時候,也不可能0秒後馬上執行,總有個最小間隔,每個瀏覽器還各不一樣,這個未做測試

我看一篇文章中說的是w3c的標準,定時器的最小時間執行是4ms,找不到出處無從考證呀! ! !

定時器相關的一些最佳化

在做定時器的時候還是可以有一些最佳化的

1.例如如果綁定window.onresize,在瀏覽器縮放的時候,該觸發的非常頻繁,所以可以延遲執行,當下次執行到的時候clear掉,減少頻繁執行

 偽代碼如下

複製程式碼 程式碼如下:

    var timer;
    function r(){
        clearTimeout(timer);
        timer = setTimeout(function(){
            //do something
        },150);       
    }

2.在滾動條往下拉的時候也是一下,比如圖片的lazyload,也應該有一個定時器,避免過多的計算

3.當有多個地方需要定時器的時候,可以合併成一個定時器,時間間隔以最小的那個為準,然後需要執行的回調函數往數組裡面塞,當到了時間間隔,遍歷數組執行即可

 一個小demo

複製程式碼 程式碼如下:




   
   



   

       
0

       
0

       
0

       
0

   

">http://static.paipaiimg.com/paipai_h5/js/ttj/zepto.min.js">>
   
        var runTime = {
            選項:{
                步驟:1000
            },
            回調:[],
            addCallbacks : [],
            開始:假,
            計時器:空,
            擴充:函數(){
                var 目標 = 參數[0] || {},i = 1,長度=arguments.length,選項;
                if ( typeof target != "object" && typeof target != "function" )
                    目標 = {};
                為 ( ; i                     if ( (options = argument[ i ]) != null )
                        for ( 選項中的 var 姓名 ) {
                            var copy = options[姓名 ];
                            if ( 目標 === 複製 )
                                續中;
                           if (複製!==未定義)
                               , 目標[姓名]=複製;
                        }
                回復目標;
            },
            初始化:函數(選項){
                $.extend(this,this.options,options||{});
            },
            新增:功能(樂趣,選項){
                選項 = 選項 ||{};
                this.addCallbacks.push({
                    有趣       : 有趣,
                    startTime : new Date().getTime(),
                    步驟     : options.step ||此一步,
                    我        : 1
                });
                var self = this;
                if(!this.start){
                    this.callbacks = [有趣];
                    this.start = true;
                    this.startTime = new Date().getTime();
                    this.timer = setInterval(function(){
                        self.done();   
                      
                    },此步驟);
                }
            },
            完成:函數(){
                varcallbacks = this.callbacks,
                    自我=這個,
                    newArr = [];
                $.each(回呼,函數(i,obj){
                    if(obj.step == self.step){
                        obj.fun();
                    }否則{                                          if(obj.i == obj.step/self.step){
                            if((new Date().getTime())-obj.startTime>obj.step*2/3){
                               obj.fun();
;
;                             }
                            obj.i = 1;
                        }其他{
                            obj.i = obj.i 1;
                        }
                    }
                });
                $.each(this.addCallbacks,function(i,obj){
                    if(obj.step == self.step){
                        if((new Date().getTime())-obj.startTime>obj.step*2/3){
                           obj.fun();
                            回復.push(obj);
                        }其他{
                            newArr.push(obj);
                        }
                    }其他{
                        obj.i = obj.i 1;
                        回復.push(obj);
                    }
                });
                this.addCallbacks = newArr;
            },
            清除:函數(){
                clearInterval(this.timer);
            }
        }
        runTime.init();

        runTime.add(function(){
            a1.innerHTML = ~~a1.innerHTML 1;
        });

        runTime.add(function(){
            a2.innerHTML = ~~a2.innerHTML 1;
        },{步驟:2000});

        runTime.add(function(){
            a3.innerHTML = ~~a3.innerHTML 1;
        },{步長:4000});
                runTime.add(function(){
            a4.innerHTML = ~~a4.innerHTML 1;
        },{步長:8000});
    腳本>
身體>

小夥伴們是否對javascript有所了解呢,如有疑問給我留言吧。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
Python和JavaScript的未來:趨勢和預測Python和JavaScript的未來:趨勢和預測Apr 27, 2025 am 12:21 AM

Python和JavaScript的未來趨勢包括:1.Python將鞏固在科學計算和AI領域的地位,2.JavaScript將推動Web技術發展,3.跨平台開發將成為熱門,4.性能優化將是重點。兩者都將繼續在各自領域擴展應用場景,並在性能上有更多突破。

Python vs. JavaScript:開發環境和工具Python vs. JavaScript:開發環境和工具Apr 26, 2025 am 12:09 AM

Python和JavaScript在開發環境上的選擇都很重要。 1)Python的開發環境包括PyCharm、JupyterNotebook和Anaconda,適合數據科學和快速原型開發。 2)JavaScript的開發環境包括Node.js、VSCode和Webpack,適用於前端和後端開發。根據項目需求選擇合適的工具可以提高開發效率和項目成功率。

JavaScript是用C編寫的嗎?檢查證據JavaScript是用C編寫的嗎?檢查證據Apr 25, 2025 am 12:15 AM

是的,JavaScript的引擎核心是用C語言編寫的。 1)C語言提供了高效性能和底層控制,適合JavaScript引擎的開發。 2)以V8引擎為例,其核心用C 編寫,結合了C的效率和麵向對象特性。 3)JavaScript引擎的工作原理包括解析、編譯和執行,C語言在這些過程中發揮關鍵作用。

JavaScript的角色:使網絡交互和動態JavaScript的角色:使網絡交互和動態Apr 24, 2025 am 12:12 AM

JavaScript是現代網站的核心,因為它增強了網頁的交互性和動態性。 1)它允許在不刷新頁面的情況下改變內容,2)通過DOMAPI操作網頁,3)支持複雜的交互效果如動畫和拖放,4)優化性能和最佳實踐提高用戶體驗。

C和JavaScript:連接解釋C和JavaScript:連接解釋Apr 23, 2025 am 12:07 AM

C 和JavaScript通過WebAssembly實現互操作性。 1)C 代碼編譯成WebAssembly模塊,引入到JavaScript環境中,增強計算能力。 2)在遊戲開發中,C 處理物理引擎和圖形渲染,JavaScript負責遊戲邏輯和用戶界面。

從網站到應用程序:JavaScript的不同應用從網站到應用程序:JavaScript的不同應用Apr 22, 2025 am 12:02 AM

JavaScript在網站、移動應用、桌面應用和服務器端編程中均有廣泛應用。 1)在網站開發中,JavaScript與HTML、CSS一起操作DOM,實現動態效果,並支持如jQuery、React等框架。 2)通過ReactNative和Ionic,JavaScript用於開發跨平台移動應用。 3)Electron框架使JavaScript能構建桌面應用。 4)Node.js讓JavaScript在服務器端運行,支持高並發請求。

Python vs. JavaScript:比較用例和應用程序Python vs. JavaScript:比較用例和應用程序Apr 21, 2025 am 12:01 AM

Python更適合數據科學和自動化,JavaScript更適合前端和全棧開發。 1.Python在數據科學和機器學習中表現出色,使用NumPy、Pandas等庫進行數據處理和建模。 2.Python在自動化和腳本編寫方面簡潔高效。 3.JavaScript在前端開發中不可或缺,用於構建動態網頁和單頁面應用。 4.JavaScript通過Node.js在後端開發中發揮作用,支持全棧開發。

C/C在JavaScript口譯員和編譯器中的作用C/C在JavaScript口譯員和編譯器中的作用Apr 20, 2025 am 12:01 AM

C和C 在JavaScript引擎中扮演了至关重要的角色,主要用于实现解释器和JIT编译器。1)C 用于解析JavaScript源码并生成抽象语法树。2)C 负责生成和执行字节码。3)C 实现JIT编译器,在运行时优化和编译热点代码,显著提高JavaScript的执行效率。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

mPDF

mPDF

mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),