亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

JavaScript是否保證是單線程的?

JavaScript是否保證是單線程的?

幕布斯6054654 2019-05-31 17:06:11
JavaScript是否保證是單線程的?眾所周知,JavaScript在所有現代瀏覽器實現中都是單線程的,但它是在任何標準中指定的,還是僅僅是傳統的呢?假設JavaScript始終是單線程的,這完全安全嗎?
查看完整描述

4 回答

?
烙印99

TA貢獻1829條經驗 獲得超13個贊

這是個好問題。我很想說“是”。我不行。


JavaScript通常被認為具有腳本(*)可見的單個執行線程,因此當輸入內聯腳本、事件偵聽器或超時,您將完全處于控制狀態,直到從塊或函數的末尾返回。


(*:忽略瀏覽器是否真的使用一個OS線程來實現他們的JS引擎,或者其他有限的執行線程是否是由WebWorker引入的問題)。


然而,在現實中不完全是真的以卑鄙的方式。


最常見的情況是立即發生的事件。當您的代碼做了什么事情導致它們時,瀏覽器會立即觸發它們:


var l= document.getElementById('log');

var i= document.getElementById('inp');

i.onblur= function() {

    l.value+= 'blur\n';

};

setTimeout(function() {

    l.value+= 'log in\n';

    l.focus();

    l.value+= 'log out\n';

}, 100);

i.focus();

<textarea id="log" rows="20" cols="40"></textarea>

<input id="inp">

結果log in, blur, log out除了IE。這些事件不只是因為你打電話focus()直接的,他們可能會發生,因為你打電話給alert(),或者打開一個彈出窗口,或者其他任何移動焦點的東西。


這也可能導致其他事件。例如,添加一個i.onchange偵聽器并在輸入中鍵入focus()調用沒有焦點,日志順序是log in, change, blur, log out,除了在歌劇院log in, blur, log out, change以及IE在哪里(更難解釋)log in, change, log out, blur.


類似調用click()元素上,該元素將調用onclick在所有瀏覽器中立即執行處理程序(至少這是一致的!)


(我用的是直接on...事件處理程序屬性,但同樣發生在addEventListener和attachEvent.)


還有很多種情況,在這些情況下,您的代碼被線程化時,事件可能會觸發,盡管您已經這樣做了。沒什么挑起它。例如:


var l= document.getElementById('log');

document.getElementById('act').onclick= function() {

    l.value+= 'alert in\n';

    alert('alert!');

    l.value+= 'alert out\n';

};

window.onresize= function() {

    l.value+= 'resize\n';

};

<textarea id="log" rows="20" cols="40"></textarea>

<button id="act">alert</button>

命中alert你會得到一個模態對話框。除非你拒絕那個對話,否則不會再執行劇本了,是嗎?沒有。調整主窗口的大小,您將得到alert in, resize, alert out在文本區域。


您可能會認為,在模式對話框打開時,不可能調整窗口的大小,但并非如此:在Linux中,您可以任意調整窗口的大??;在Windows上,這并不容易,但您可以通過將屏幕分辨率從更大的更改為不適合窗口的更小的分辨率來實現,從而調整窗口的大小。


你可能會想,嗯,這只是resize(可能還有更多的scroll),因為腳本是線程的,所以當用戶沒有與瀏覽器進行主動交互時,它就會觸發。對于單一窗口,你可能是對的。但是,當你做跨窗口腳本時,這一切都會被拋到腦后。對于除Safari之外的所有瀏覽器,在任何一個瀏覽器繁忙時都會阻塞所有窗口/選項卡/框架,您可以從另一個文檔的代碼中與文檔交互,運行在單獨的執行線程中,并導致任何相關的事件處理程序被觸發。

可以在腳本仍然線程化的情況下引發您可以導致生成的事件的地方:

  • 當模態彈出時(alertconfirmprompt在除Opera之外的所有瀏覽器中都是開放的;

  • 期間showModalDialog在支持它的瀏覽器上;

  • “這頁上的劇本可能很忙.”對話框,即使你選擇讓腳本繼續運行,允許像調整大小和模糊事件觸發和處理,即使腳本是在繁忙的循環中間,除了在Opera。

  • 不久前,對于我來說,在IE中使用Sun Java插件,調用applet上的任何方法都可能允許事件觸發并重新輸入腳本。這一直是一個時間敏感的錯誤,有可能Sun已經修復了它(我當然希望如此)。

  • 可能更多。我已經有一段時間沒有對此進行測試了,從那時起瀏覽器就變得越來越復雜了。

總之,在大多數用戶看來,JavaScript似乎有一個嚴格的事件驅動的單線程執行。實際上,它沒有這樣的東西。目前還不清楚這其中有多少只是一個bug,有多少是刻意設計的,但如果你在編寫復雜的應用程序,特別是跨窗口/框架腳本的應用程序,它很有可能會咬你一口-而且是間歇性的、難以調試的方式。

如果最壞的情況發生在最壞的情況下,您可以通過引導所有事件響應來解決并發問題。當事件出現時,將其放到隊列中,然后按順序處理隊列,然后在setInterval功能。如果您正在編寫一個您想要被復雜應用程序使用的框架,那么這樣做可能是一個不錯的舉動。postMessage也有希望在未來緩解跨文檔腳本的痛苦。


查看完整回答
反對 回復 2019-05-31
?
哆啦的時光機

TA貢獻1779條經驗 獲得超6個贊

我會說是的,因為如果瀏覽器的javascript引擎異步運行,幾乎所有現存的(至少是所有重要的)javascript代碼都會中斷。

再加上一個事實HTML 5已經指定了Web工作者(一個明確的、標準化的多線程javascript代碼API)在基本Javascript中引入多線程基本上是沒有意義的。

(給其他人的評論:即使setTimeout/setInterval,HTTP-請求onload事件(XHR)和UI事件(單擊、焦點等)給人一種簡單的多重性印象-它們仍然都是沿著一個時間線執行的-一次一條-所以即使我們事先不知道它們的執行順序,也沒有必要擔心事件處理程序、時間函數或XHR回調的執行過程中外部條件的變化。)


查看完整回答
反對 回復 2019-05-31
?
繁花不似錦

TA貢獻1851條經驗 獲得超4個贊

是的,盡管在使用任何異步API(如setInterval和xmlhttp回調)時仍然會遇到并發編程的一些問題(主要是爭用條件)。


查看完整回答
反對 回復 2019-05-31
?
慕仙森

TA貢獻1827條經驗 獲得超8個贊

是的,雖然InternetExplorer 9將在一個單獨的線程上編譯Javascript,以準備在主線程上執行。不過,作為一個程序員,這不會改變任何事情。


查看完整回答
反對 回復 2019-05-31
  • 4 回答
  • 0 關注
  • 559 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號