整合營銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          JavaScript 運(yùn)行機(jī)制(Event Loop

          JavaScript 運(yùn)行機(jī)制(Event Loop)詳解

          、為什么JavaScript是單線程?

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

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

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

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

          二、任務(wù)隊列

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

          如果排隊是因?yàn)橛嬎懔看?,CPU忙不過來,倒也算了,但是很多時候CPU是閑著的,因?yàn)镮O設(shè)備(輸入輸出設(shè)備)很慢(比如Ajax操作從網(wǎng)絡(luò)讀取數(shù)據(jù)),不得不等著結(jié)果出來,再往下執(zhí)行。

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

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

          具體來說,異步執(zhí)行的運(yùn)行機(jī)制如下。(同步執(zhí)行也是如此,因?yàn)樗梢员灰暈闆]有異步任務(wù)的異步執(zhí)行。)

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

          只要主線程空了,就會去讀取"任務(wù)隊列",這就是JavaScript的運(yùn)行機(jī)制。這個過程會不斷重復(fù)。

          三、事件和回調(diào)函數(shù)

          "任務(wù)隊列"是一個事件的隊列(也可以理解成消息的隊列),IO設(shè)備完成一項(xiàng)任務(wù),就在"任務(wù)隊列"中添加一個事件,表示相關(guān)的異步任務(wù)可以進(jìn)入"執(zhí)行棧"了。主線程讀取"任務(wù)隊列",就是讀取里面有哪些事件。

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

          所謂"回調(diào)函數(shù)"(callback),就是那些會被主線程掛起來的代碼。異步任務(wù)必須指定回調(diào)函數(shù),當(dāng)主線程開始執(zhí)行異步任務(wù),就是執(zhí)行對應(yīng)的回調(diào)函數(shù)。

          "任務(wù)隊列"是一個先進(jìn)先出的數(shù)據(jù)結(jié)構(gòu),排在前面的事件,優(yōu)先被主線程讀取。主線程的讀取過程基本上是自動的,只要執(zhí)行棧一清空,"任務(wù)隊列"上第一位的事件就自動進(jìn)入主線程。但是,由于存在后文提到的"定時器"功能,主線程首先要檢查一下執(zhí)行時間,某些事件只有到了規(guī)定的時間,才能返回主線程。

          四、Event Loop

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

          五、定時器

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

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

          setTimeout()接受兩個參數(shù),第一個是回調(diào)函數(shù),第二個是推遲執(zhí)行的毫秒數(shù)。

          如果將setTimeout()的第二個參數(shù)設(shè)為0,就表示當(dāng)前代碼執(zhí)行完(執(zhí)行棧清空)以后,立即執(zhí)行(0毫秒間隔)指定的回調(diào)函數(shù)。

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

          console.log(2);

          上面代碼的執(zhí)行結(jié)果總是2,1,因?yàn)橹挥性趫?zhí)行完第二行以后,系統(tǒng)才會去執(zhí)行"任務(wù)隊列"中的回調(diào)函數(shù)。

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

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

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

          六、Node.js的Event Loop

          Node.js也是單線程的Event Loop,但是它的運(yùn)行機(jī)制不同于瀏覽器環(huán)境。

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

          process.nextTick方法可以在當(dāng)前"執(zhí)行棧"的尾部----下一次Event Loop(主線程讀取"任務(wù)隊列")之前----觸發(fā)回調(diào)函數(shù)。也就是說,它指定的任務(wù)總是發(fā)生在所有異步任務(wù)之前。setImmediate方法則是在當(dāng)前"任務(wù)隊列"的尾部添加事件,也就是說,它指定的任務(wù)總是在下一次Event Loop時執(zhí)行,這與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方法指定的回調(diào)函數(shù),總是在當(dāng)前"執(zhí)行棧"的尾部觸發(fā),所以不僅函數(shù)A比setTimeout指定的回調(diào)函數(shù)timeout先執(zhí)行,而且函數(shù)B也比timeout先執(zhí)行。這說明,如果有多個process.nextTick語句(不管它們是否嵌套),將全部在當(dāng)前"執(zhí)行棧"執(zhí)行

          現(xiàn)在,再看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)各自添加了一個回調(diào)函數(shù)A和timeout,都是在下一次Event Loop觸發(fā)。那么,哪個回調(diào)函數(shù)先執(zhí)行呢?答案是不確定。運(yùn)行結(jié)果可能是1--TIMEOUT FIRED--2,也可能是TIMEOUT FIRED--1--2。

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

          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里面,它的運(yùn)行結(jié)果總是1--TIMEOUT FIRED--2,這時函數(shù)A一定在timeout前面觸發(fā)。至于2排在TIMEOUT FIRED的后面(即函數(shù)B在timeout后面觸發(fā)),是因?yàn)閟etImmediate總是將事件注冊到下一輪Event Loop,所以函數(shù)A和timeout是在同一輪Loop執(zhí)行,而函數(shù)B在下一輪Loop執(zhí)行。

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

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

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

          另外,由于process.nextTick指定的回調(diào)函數(shù)是在本次"事件循環(huán)"觸發(fā),而setImmediate指定的是在下次"事件循環(huán)"觸發(fā),所以很顯然,前者總是比后者發(fā)生得早,而且執(zhí)行效率也高(因?yàn)椴挥脵z查"任務(wù)隊列")。

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

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

          <!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頁面內(nèi)容執(zhí)行順序</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頁面內(nèi)容的加載是順序加載,也就是在html頁面中前面先加載,因此當(dāng)加載到JS腳本時,input還沒有加載到瀏覽器中。JS是一種解釋性的腳本,也是從上而下順序執(zhí)行,由于這段JS代碼是立即執(zhí)行的,所以當(dāng)JS在執(zhí)行的時候,讀取不到input的值。

          最直接的修改方法是把JS放到網(wǎng)頁的最下面執(zhí)行。

          <!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頁面內(nèi)容執(zhí)行順序</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放到網(wǎng)頁的最下面,這樣在JS執(zhí)行的時候,網(wǎng)頁內(nèi)容都已經(jīng)加載完畢。把JS放在網(wǎng)頁的最下面方法并不是最好的解決方法,大部分情況JS并不是總能放在網(wǎng)頁的最下面。這時可以用window的onload事件,onload事件在整個頁面都加載完成后才觸發(fā),可以把JS腳本放在onload里面執(zhí)行。不同瀏覽器onload事件添加方式也不一樣。

          IE下事件:

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

          Chrome/Firefox等DOM標(biāo)準(zhǔn)事件:

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

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

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

          上面方法本質(zhì)就是添加onload監(jiān)聽事件。

          最終修改后的頁面

          HTML DOM 事件

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

          事件通常與函數(shù)結(jié)合使用,函數(shù)不會在事件發(fā)生前被執(zhí)行! (如用戶點(diǎn)擊按鈕)。

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

          HTML DOM 事件

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

          鼠標(biāo)事件

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

          鍵盤事件

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

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

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

          表單事件

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

          剪貼板事件

          屬性描述DOM
          oncopy該事件在用戶拷貝元素內(nèi)容時觸發(fā)
          oncut該事件在用戶剪切元素內(nèi)容時觸發(fā)
          onpaste該事件在用戶粘貼元素內(nèi)容時觸發(fā)

          打印事件

          屬性描述DOM
          onafterprint該事件在頁面已經(jīng)開始打印,或者打印窗口已經(jīng)關(guān)閉時觸發(fā)
          onbeforeprint該事件在頁面即將開始打印時觸發(fā)

          拖動事件

          事件描述DOM
          ondrag該事件在元素正在拖動時觸發(fā)
          ondragend該事件在用戶完成元素的拖動時觸發(fā)
          ondragenter該事件在拖動的元素進(jìn)入放置目標(biāo)時觸發(fā)
          ondragleave該事件在拖動元素離開放置目標(biāo)時觸發(fā)
          ondragover該事件在拖動元素在放置目標(biāo)上時觸發(fā)
          ondragstart該事件在用戶開始拖動元素時觸發(fā)
          ondrop該事件在拖動元素放置在目標(biāo)區(qū)域時觸發(fā)

          多媒體(Media)事件

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

          動畫事件

          事件描述DOM
          animationend該事件在 CSS 動畫結(jié)束播放時觸發(fā)
          animationiteration該事件在 CSS 動畫重復(fù)播放時觸發(fā)
          animationstart該事件在 CSS 動畫開始播放時觸發(fā)

          過渡事件

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

          其他事件

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

          事件對象

          常量

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

          屬性

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

          方法

          方法描述DOM
          initEvent()初始化新創(chuàng)建的 Event 對象的屬性。2
          preventDefault()通知瀏覽器不要執(zhí)行與事件關(guān)聯(lián)的默認(rèn)動作。2
          stopPropagation()不再派發(fā)事件。2

          目標(biāo)事件對象

          方法

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

          事件監(jiān)聽對象

          方法

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

          文檔事件對象

          方法

          方法描述DOM
          createEvent()2

          鼠標(biāo)/鍵盤事件對象

          屬性

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

          方法

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

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


          主站蜘蛛池模板: 日韩在线不卡免费视频一区| 99精品一区二区三区| 亚洲国产AV无码一区二区三区| 中文字幕AV无码一区二区三区| 国偷自产视频一区二区久| 亚洲国产日韩一区高清在线| 欧洲精品一区二区三区在线观看| 久久精品人妻一区二区三区 | 久久中文字幕一区二区| 99在线精品一区二区三区| 中文字幕aⅴ人妻一区二区 | 人妻体体内射精一区二区| 日韩精品一区二区三区视频| 91在线一区二区三区| 久久久久人妻一区二区三区 | 91在线一区二区三区| 亚洲国产精品一区| 农村人乱弄一区二区 | 亚洲不卡av不卡一区二区| 精品久久久久久中文字幕一区| 中文字幕久久亚洲一区| 国产人妖视频一区二区| 亚洲AV综合色一区二区三区 | 亚洲AV无码一区二区三区牛牛| 日韩人妻无码一区二区三区| 一区二区三区91| 在线观看国产一区二区三区| 内射白浆一区二区在线观看| 精品国产一区二区三区在线| 国产在线一区二区视频| 国产在线精品一区二区| 欧洲精品码一区二区三区免费看 | 看电影来5566一区.二区| 亚洲欧美日韩国产精品一区| 国产精品无码一区二区在线 | 久久99国产精一区二区三区| 国产一区视频在线| 亚洲日本va一区二区三区 | 夜精品a一区二区三区| 狠狠综合久久AV一区二区三区| 久久精品亚洲一区二区三区浴池 |