Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 国内精品久久久久久久试看,中文字幕精品一区二区三区视频,欧美做爰猛烈床戏大尺度

          整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          JavaScript 運行機制(Event Loop

          JavaScript 運行機制(Event Loop)詳解

          、為什么JavaScript是單線程?

          JavaScript語言的一大特點就是單線程,也就是說,同一個時間只能做一件事。那么,為什么JavaScript不能有多個線程呢?這樣能提高效率啊。

          JavaScript的單線程,與它的用途有關。作為瀏覽器腳本語言,JavaScript的主要用途是與用戶互動,以及操作DOM。這決定了它只能是單線程,否則會帶來很復雜的同步問題。比如,假定JavaScript同時有兩個線程,一個線程在某個DOM節點上添加內容,另一個線程刪除了這個節點,這時瀏覽器應該以哪個線程為準?

          所以,為了避免復雜性,從一誕生,JavaScript就是單線程,這已經成了這門語言的核心特征,將來也不會改變。

          為了利用多核CPU的計算能力,HTML5提出Web Worker標準,允許JavaScript腳本創建多個線程,但是子線程完全受主線程控制,且不得操作DOM。所以,這個新標準并沒有改變JavaScript單線程的本質。

          二、任務隊列

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

          如果排隊是因為計算量大,CPU忙不過來,倒也算了,但是很多時候CPU是閑著的,因為IO設備(輸入輸出設備)很慢(比如Ajax操作從網絡讀取數據),不得不等著結果出來,再往下執行。

          JavaScript語言的設計者意識到,這時主線程完全可以不管IO設備,掛起處于等待中的任務,先運行排在后面的任務。等到IO設備返回了結果,再回過頭,把掛起的任務繼續執行下去。

          于是,所有任務可以分成兩種,一種是同步任務(synchronous),另一種是異步任務(asynchronous)。同步任務指的是,在主線程上排隊執行的任務,只有前一個任務執行完畢,才能執行后一個任務;異步任務指的是,不進入主線程、而進入"任務隊列"(task queue)的任務,只有"任務隊列"通知主線程,某個異步任務可以執行了,該任務才會進入主線程執行。

          具體來說,異步執行的運行機制如下。(同步執行也是如此,因為它可以被視為沒有異步任務的異步執行。)

          • (1)所有同步任務都在主線程上執行,形成一個執行棧(execution context stack)。
          • (2)主線程之外,還存在一個"任務隊列"(task queue)。只要異步任務有了運行結果,就在"任務隊列"之中放置一個事件。
          • (3)一旦"執行棧"中的所有同步任務執行完畢,系統就會讀取"任務隊列",看看里面有哪些事件。那些對應的異步任務,于是結束等待狀態,進入執行棧,開始執行。
          • (4)主線程不斷重復上面的第三步。

          只要主線程空了,就會去讀取"任務隊列",這就是JavaScript的運行機制。這個過程會不斷重復。

          三、事件和回調函數

          "任務隊列"是一個事件的隊列(也可以理解成消息的隊列),IO設備完成一項任務,就在"任務隊列"中添加一個事件,表示相關的異步任務可以進入"執行棧"了。主線程讀取"任務隊列",就是讀取里面有哪些事件。

          "任務隊列"中的事件,除了IO設備的事件以外,還包括一些用戶產生的事件(比如鼠標點擊、頁面滾動等等)。只要指定過回調函數,這些事件發生時就會進入"任務隊列",等待主線程讀取。

          所謂"回調函數"(callback),就是那些會被主線程掛起來的代碼。異步任務必須指定回調函數,當主線程開始執行異步任務,就是執行對應的回調函數。

          "任務隊列"是一個先進先出的數據結構,排在前面的事件,優先被主線程讀取。主線程的讀取過程基本上是自動的,只要執行棧一清空,"任務隊列"上第一位的事件就自動進入主線程。但是,由于存在后文提到的"定時器"功能,主線程首先要檢查一下執行時間,某些事件只有到了規定的時間,才能返回主線程。

          四、Event Loop

          主線程從"任務隊列"中讀取事件,這個過程是循環不斷的,所以整個的這種運行機制又稱為Event Loop(事件循環)。

          五、定時器

          除了放置異步任務的事件,"任務隊列"還可以放置定時事件,即指定某些代碼在多少時間之后執行。這叫做"定時器"(timer)功能,也就是定時執行的代碼。

          定時器功能主要由setTimeout()和setInterval()這兩個函數來完成,它們的內部運行機制完全一樣,區別在于前者指定的代碼是一次性執行,后者則為反復執行。以下主要討論setTimeout()。

          setTimeout()接受兩個參數,第一個是回調函數,第二個是推遲執行的毫秒數。

          如果將setTimeout()的第二個參數設為0,就表示當前代碼執行完(執行棧清空)以后,立即執行(0毫秒間隔)指定的回調函數。

          setTimeout(function(){console.log(1);}, 0);

          console.log(2);

          上面代碼的執行結果總是2,1,因為只有在執行完第二行以后,系統才會去執行"任務隊列"中的回調函數。

          總之,setTimeout(fn,0)的含義是,指定某個任務在主線程最早可得的空閑時間執行,也就是說,盡可能早得執行。它在"任務隊列"的尾部添加一個事件,因此要等到同步任務和"任務隊列"現有的事件都處理完,才會得到執行。

          HTML5標準規定了setTimeout()的第二個參數的最小值(最短間隔),不得低于4毫秒,如果低于這個值,就會自動增加。在此之前,老版本的瀏覽器都將最短間隔設為10毫秒。另外,對于那些DOM的變動(尤其是涉及頁面重新渲染的部分),通常不會立即執行,而是每16毫秒執行一次。這時使用requestAnimationFrame()的效果要好于setTimeout()。

          需要注意的是,setTimeout()只是將事件插入了"任務隊列",必須等到當前代碼(執行棧)執行完,主線程才會去執行它指定的回調函數。要是當前代碼耗時很長,有可能要等很久,所以并沒有辦法保證,回調函數一定會在setTimeout()指定的時間執行。

          六、Node.js的Event Loop

          Node.js也是單線程的Event Loop,但是它的運行機制不同于瀏覽器環境。

          除了setTimeout和setInterval這兩個方法,Node.js還提供了另外兩個與"任務隊列"有關的方法:process.nextTick和setImmediate。它們可以幫助我們加深對"任務隊列"的理解。

          process.nextTick方法可以在當前"執行棧"的尾部----下一次Event Loop(主線程讀取"任務隊列")之前----觸發回調函數。也就是說,它指定的任務總是發生在所有異步任務之前。setImmediate方法則是在當前"任務隊列"的尾部添加事件,也就是說,它指定的任務總是在下一次Event Loop時執行,這與setTimeout(fn, 0)很像。請看下面的例子

          process.nextTick(function A() {
           console.log(1);
           process.nextTick(function B(){console.log(2);});
          });
          setTimeout(function timeout() {
           console.log('TIMEOUT FIRED');
          }, 0)
          // 1
          // 2
          // TIMEOUT FIRED
          

          上面代碼中,由于process.nextTick方法指定的回調函數,總是在當前"執行棧"的尾部觸發,所以不僅函數A比setTimeout指定的回調函數timeout先執行,而且函數B也比timeout先執行。這說明,如果有多個process.nextTick語句(不管它們是否嵌套),將全部在當前"執行棧"執行

          現在,再看setImmediate。

          setImmediate(function A() {
           console.log(1);
           setImmediate(function B(){console.log(2);});
          });
          setTimeout(function timeout() {
           console.log('TIMEOUT FIRED');
          }, 0);
          

          上面代碼中,setImmediate與setTimeout(fn,0)各自添加了一個回調函數A和timeout,都是在下一次Event Loop觸發。那么,哪個回調函數先執行呢?答案是不確定。運行結果可能是1--TIMEOUT FIRED--2,也可能是TIMEOUT FIRED--1--2。

          令人困惑的是,Node.js文檔中稱,setImmediate指定的回調函數,總是排在setTimeout前面。實際上,這種情況只發生在遞歸調用的時候。

          setImmediate(function (){
           setImmediate(function A() {
           console.log(1);
           setImmediate(function B(){console.log(2);});
           });
           setTimeout(function timeout() {
           console.log('TIMEOUT FIRED');
           }, 0);
          });
          // 1
          // TIMEOUT FIRED
          // 2
          

          上面代碼中,setImmediate和setTimeout被封裝在一個setImmediate里面,它的運行結果總是1--TIMEOUT FIRED--2,這時函數A一定在timeout前面觸發。至于2排在TIMEOUT FIRED的后面(即函數B在timeout后面觸發),是因為setImmediate總是將事件注冊到下一輪Event Loop,所以函數A和timeout是在同一輪Loop執行,而函數B在下一輪Loop執行。

          我們由此得到了process.nextTick和setImmediate的一個重要區別:多個process.nextTick語句總是在當前"執行棧"一次執行完,多個setImmediate可能則需要多次loop才能執行完。事實上,這正是Node.js 10.0版添加setImmediate方法的原因,否則像下面這樣的遞歸調用process.nextTick,將會沒完沒了,主線程根本不會去讀取"事件隊列"!

          process.nextTick(function foo() {
           process.nextTick(foo);
          });
          

          事實上,現在要是你寫出遞歸的process.nextTick,Node.js會拋出一個警告,要求你改成setImmediate。

          另外,由于process.nextTick指定的回調函數是在本次"事件循環"觸發,而setImmediate指定的是在下次"事件循環"觸發,所以很顯然,前者總是比后者發生得早,而且執行效率也高(因為不用檢查"任務隊列")。

          來源:http://www.ruanyifeng.com/blog/2014/10/event-loop.html

          事跟我說他用jQuery取不到頁面上隱藏元素input的值,他的html頁面大概內容如下。

          <!DOCTYPE html>
          <html lang="zh">
           
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
          	<script type="text/javascript" src="jslib/jquery-1.11.2.min.js"></script>
          	<title>淺談Html頁面內容執行順序</title>
          	<script type="text/javascript">
          		var userId=$('#hiddenUserId').val();
          		var contextPath=$('#hiddenContextPath').val();
          		var userName=$('#hiddenUserName').val();
          	</script>
          </head>
           
          <body>
          	<input type="hidden" id="hiddenUserId" value="101" />
          	<input type="hidden" id="hiddenContextPath" value="/web" />
          	<input type="hidden" id="hiddenUserName" value="小明" />
          </body>
           
          </html>

          頁面中的JS腳本在head中,JS腳本要讀取的input在body中。瀏覽器對html頁面內容的加載是順序加載,也就是在html頁面中前面先加載,因此當加載到JS腳本時,input還沒有加載到瀏覽器中。JS是一種解釋性的腳本,也是從上而下順序執行,由于這段JS代碼是立即執行的,所以當JS在執行的時候,讀取不到input的值。

          最直接的修改方法是把JS放到網頁的最下面執行。

          <!DOCTYPE html>
          <html lang="zh">
           
          <head>
          	<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
          	<script type="text/javascript" src="jslib/jquery-1.11.2.min.js"></script>
          	<title>淺談Html頁面內容執行順序</title>	
          </head>
           
          <body>
          	<input type="hidden" id="hiddenUserId" value="101" />
          	<input type="hidden" id="hiddenContextPath" value="/web" />
          	<input type="hidden" id="hiddenUserName" value="小明" />
          	
          	<script type="text/javascript">
          		var userId=$('#hiddenUserId').val();
          		var contextPath=$('#hiddenContextPath').val();
          		var userName=$('#hiddenUserName').val();
          	</script>
          </body>
           
          </html>

          把JS放到網頁的最下面,這樣在JS執行的時候,網頁內容都已經加載完畢。把JS放在網頁的最下面方法并不是最好的解決方法,大部分情況JS并不是總能放在網頁的最下面。這時可以用window的onload事件,onload事件在整個頁面都加載完成后才觸發,可以把JS腳本放在onload里面執行。不同瀏覽器onload事件添加方式也不一樣。

          IE下事件:

          window.attachEvent('onload', function(){
          			var userId=$('#hiddenUserId').val();
          			var contextPath=$('#hiddenContextPath').val();
          			var userName=$('#hiddenUserName').val();
          		});

          Chrome/Firefox等DOM標準事件:

          window.addEventListener('load', function(){
          			var userId=$('#hiddenUserId').val();
          			var contextPath=$('#hiddenContextPath').val();
          			var userName=$('#hiddenUserName').val();
          		});

          由于不同瀏覽器的事件添加方式不一樣,jQuery為我們提供了通用的初始化方法,該方法在頁面加載完成時觸發。

          $(function(){
          			var userId=$('#hiddenUserId').val();
          			var contextPath=$('#hiddenContextPath').val();
          			var userName=$('#hiddenUserName').val();
          		});

          上面方法本質就是添加onload監聽事件。

          最終修改后的頁面

          HTML DOM 事件

          HTML DOM 事件允許Javascript在HTML文檔元素中注冊不同事件處理程序。

          事件通常與函數結合使用,函數不會在事件發生前被執行! (如用戶點擊按鈕)。

          提示: 在 W3C 2 級 DOM 事件中規范了事件模型。

          HTML DOM 事件

          DOM: 指明使用的 DOM 屬性級別。

          鼠標事件

          屬性描述DOM
          onclick當用戶點擊某個對象時調用的事件句柄。2
          oncontextmenu在用戶點擊鼠標右鍵打開上下文菜單時觸發
          ondblclick當用戶雙擊某個對象時調用的事件句柄。2
          onmousedown鼠標按鈕被按下。2
          onmouseenter當鼠標指針移動到元素上時觸發。2
          onmouseleave當鼠標指針移出元素時觸發2
          onmousemove鼠標被移動。2
          onmouseover鼠標移到某元素之上。2
          onmouseout鼠標從某元素移開。2
          onmouseup鼠標按鍵被松開。2

          鍵盤事件

          屬性描述DOM
          onkeydown某個鍵盤按鍵被按下。2
          onkeypress某個鍵盤按鍵被按下并松開。2
          onkeyup某個鍵盤按鍵被松開。2

          框架/對象(Frame/Object)事件

          屬性描述DOM
          onabort圖像的加載被中斷。 ( <object>)2
          onbeforeunload該事件在即將離開頁面(刷新或關閉)時觸發2
          onerror在加載文檔或圖像時發生錯誤。 ( <object>, <body>和 <frameset>)
          onhashchange該事件在當前 URL 的錨部分發生修改時觸發。
          onload一張頁面或一幅圖像完成加載。2
          onpageshow該事件在用戶訪問頁面時觸發
          onpagehide該事件在用戶離開當前網頁跳轉到另外一個頁面時觸發
          onresize窗口或框架被重新調整大小。2
          onscroll當文檔被滾動時發生的事件。2
          onunload用戶退出頁面。 ( <body> 和 <frameset>)2

          表單事件

          屬性描述DOM
          onblur元素失去焦點時觸發2
          onchange該事件在表單元素的內容改變時觸發( <input>, <keygen>, <select>, 和 <textarea>)2
          onfocus元素獲取焦點時觸發2
          onfocusin元素即將獲取焦點時觸發2
          onfocusout元素即將失去焦點時觸發2
          oninput元素獲取用戶輸入時觸發3
          onreset表單重置時觸發2
          onsearch用戶向搜索域輸入文本時觸發 ( <input="search">)
          onselect用戶選取文本時觸發 ( <input> 和 <textarea>)2
          onsubmit表單提交時觸發2

          剪貼板事件

          屬性描述DOM
          oncopy該事件在用戶拷貝元素內容時觸發
          oncut該事件在用戶剪切元素內容時觸發
          onpaste該事件在用戶粘貼元素內容時觸發

          打印事件

          屬性描述DOM
          onafterprint該事件在頁面已經開始打印,或者打印窗口已經關閉時觸發
          onbeforeprint該事件在頁面即將開始打印時觸發

          拖動事件

          事件描述DOM
          ondrag該事件在元素正在拖動時觸發
          ondragend該事件在用戶完成元素的拖動時觸發
          ondragenter該事件在拖動的元素進入放置目標時觸發
          ondragleave該事件在拖動元素離開放置目標時觸發
          ondragover該事件在拖動元素在放置目標上時觸發
          ondragstart該事件在用戶開始拖動元素時觸發
          ondrop該事件在拖動元素放置在目標區域時觸發

          多媒體(Media)事件

          事件描述DOM
          onabort事件在視頻/音頻(audio/video)終止加載時觸發。
          oncanplay事件在用戶可以開始播放視頻/音頻(audio/video)時觸發。
          oncanplaythrough事件在視頻/音頻(audio/video)可以正常播放且無需停頓和緩沖時觸發。
          ondurationchange事件在視頻/音頻(audio/video)的時長發生變化時觸發。
          onemptied當期播放列表為空時觸發
          onended事件在視頻/音頻(audio/video)播放結束時觸發。
          onerror事件在視頻/音頻(audio/video)數據加載期間發生錯誤時觸發。
          onloadeddata事件在瀏覽器加載視頻/音頻(audio/video)當前幀時觸發觸發。
          onloadedmetadata事件在指定視頻/音頻(audio/video)的元數據加載后觸發。
          onloadstart事件在瀏覽器開始尋找指定視頻/音頻(audio/video)觸發。
          onpause事件在視頻/音頻(audio/video)暫停時觸發。
          onplay事件在視頻/音頻(audio/video)開始播放時觸發。
          onplaying事件在視頻/音頻(audio/video)暫停或者在緩沖后準備重新開始播放時觸發。
          onprogress事件在瀏覽器下載指定的視頻/音頻(audio/video)時觸發。
          onratechange事件在視頻/音頻(audio/video)的播放速度發送改變時觸發。
          onseeked事件在用戶重新定位視頻/音頻(audio/video)的播放位置后觸發。
          onseeking事件在用戶開始重新定位視頻/音頻(audio/video)時觸發。
          onstalled事件在瀏覽器獲取媒體數據,但媒體數據不可用時觸發。
          onsuspend事件在瀏覽器讀取媒體數據中止時觸發。
          ontimeupdate事件在當前的播放位置發送改變時觸發。
          onvolumechange事件在音量發生改變時觸發。
          onwaiting事件在視頻由于要播放下一幀而需要緩沖時觸發。

          動畫事件

          事件描述DOM
          animationend該事件在 CSS 動畫結束播放時觸發
          animationiteration該事件在 CSS 動畫重復播放時觸發
          animationstart該事件在 CSS 動畫開始播放時觸發

          過渡事件

          事件描述DOM
          transitionend該事件在 CSS 完成過渡后觸發。

          其他事件

          事件描述DOM
          onmessage該事件通過或者從對象(WebSocket, Web Worker, Event Source 或者子 frame 或父窗口)接收到消息時觸發
          onmousewheel已廢棄。 使用 onwheel 事件替代
          ononline該事件在瀏覽器開始在線工作時觸發。
          onoffline該事件在瀏覽器開始離線工作時觸發。
          onpopstate該事件在窗口的瀏覽歷史(history 對象)發生改變時觸發。
          onshow該事件當 <menu> 元素在上下文菜單顯示時觸發
          onstorage該事件在 Web Storage(HTML 5 Web 存儲)更新時觸發
          ontoggle該事件在用戶打開或關閉 <details> 元素時觸發
          onwheel該事件在鼠標滾輪在元素上下滾動時觸發

          事件對象

          常量

          靜態變量描述DOM
          CAPTURING-PHASE當前事件階段為捕獲階段(3)1
          AT-TARGET當前事件是目標階段,在評估目標事件(1)2
          BUBBLING-PHASE當前的事件為冒泡階段 (2)3

          屬性

          屬性描述DOM
          bubbles返回布爾值,指示事件是否是起泡事件類型。2
          cancelable返回布爾值,指示事件是否可擁可取消的默認動作。2
          currentTarget返回其事件監聽器觸發該事件的元素。2
          eventPhase返回事件傳播的當前階段。2
          target返回觸發此事件的元素(事件的目標節點)。2
          timeStamp返回事件生成的日期和時間。2
          type返回當前 Event 對象表示的事件的名稱。2

          方法

          方法描述DOM
          initEvent()初始化新創建的 Event 對象的屬性。2
          preventDefault()通知瀏覽器不要執行與事件關聯的默認動作。2
          stopPropagation()不再派發事件。2

          目標事件對象

          方法

          方法描述DOM
          addEventListener()允許在目標事件中注冊監聽事件(IE8=attachEvent())2
          dispatchEvent()允許發送事件到監聽器上 (IE8=fireEvent())2
          removeEventListener()運行一次注冊在事件目標上的監聽事件(IE8=detachEvent())2

          事件監聽對象

          方法

          方法描述DOM
          handleEvent()把任意對象注冊為事件處理程序2

          文檔事件對象

          方法

          方法描述DOM
          createEvent()2

          鼠標/鍵盤事件對象

          屬性

          屬性描述DOM
          altKey返回當事件被觸發時,"ALT" 是否被按下。2
          button返回當事件被觸發時,哪個鼠標按鈕被點擊。2
          clientX返回當事件被觸發時,鼠標指針的水平坐標。2
          clientY返回當事件被觸發時,鼠標指針的垂直坐標。2
          ctrlKey返回當事件被觸發時,"CTRL" 鍵是否被按下。2
          Location返回按鍵在設備上的位置3
          charCode返回onkeypress事件觸發鍵值的字母代碼。2
          key在按下按鍵時返回按鍵的標識符。3
          keyCode返回onkeypress事件觸發的鍵的值的字符代碼,或者 onkeydown 或 onkeyup 事件的鍵的代碼。2
          which返回onkeypress事件觸發的鍵的值的字符代碼,或者 onkeydown 或 onkeyup 事件的鍵的代碼。2
          metaKey返回當事件被觸發時,"meta" 鍵是否被按下。2
          relatedTarget返回與事件的目標節點相關的節點。2
          screenX返回當某個事件被觸發時,鼠標指針的水平坐標。2
          screenY返回當某個事件被觸發時,鼠標指針的垂直坐標。2
          shiftKey返回當事件被觸發時,"SHIFT" 鍵是否被按下。2

          方法

          方法描述W3C
          initMouseEvent()初始化鼠標事件對象的值2
          initKeyboardEvent()初始化鍵盤事件對象的值3

          如您還有不明白的可以在下面與我留言或是與我探討QQ群308855039,我們一起飛!


          主站蜘蛛池模板: 精品一区二区ww| av一区二区三区人妻少妇| 久久se精品一区二区国产| 日韩精品无码免费一区二区三区| 国产精品一区二区无线| 一区二区在线观看视频| 国产麻豆精品一区二区三区v视界| 国产中文字幕一区| 亚洲国产AV无码一区二区三区| 精品国产一区二区三区久久| 岛国精品一区免费视频在线观看| 成人丝袜激情一区二区| 3D动漫精品一区二区三区| 亚洲一区综合在线播放| 日本不卡一区二区视频a| 中文字幕精品无码一区二区| 国产精品污WWW一区二区三区 | 日韩A无码AV一区二区三区 | 精品在线视频一区| 99偷拍视频精品一区二区| 国产精品一区二区毛卡片| 国产伦精品一区二区三区不卡| 亚洲丶国产丶欧美一区二区三区| 色婷婷av一区二区三区仙踪林| 亚洲欧美一区二区三区日产| 性色AV一区二区三区天美传媒| 日本高清一区二区三区| 国产精品无码一区二区三区不卡 | 中日av乱码一区二区三区乱码| 一区二区三区日本电影| 一区二区三区免费视频播放器| 无码欧精品亚洲日韩一区夜夜嗨 | 亚洲AV成人精品日韩一区18p | 日韩AV在线不卡一区二区三区| 精彩视频一区二区三区| 精品一区二区在线观看| 中文字幕永久一区二区三区在线观看 | 日本在线观看一区二区三区| 国产精品亚洲高清一区二区| 伊人久久精品无码av一区| 国产精品区一区二区三在线播放|