事件委託和this

JavaScript不只門檻低,並且是一門有趣、功能強大和很是重要的語言。各行各業的人發現本身最混亂的選擇是JavaSscript編程語言。因爲有着各類各樣的背景,因此不是每一個人都對JavaScript及其基本原理有普遍的認識。一般來書,除非你去參加工做面試纔會去思考爲何或者怎麼作,不然JavaScript只是你工做的內容。javascript

這個系類的目標是深刻探討JavaScript的一些概念和理論。主題來自於 Darcy Clarke的JavaScript典型面試問題列表。但願你不只僅是爲了答案而閱讀完這篇文章,每一篇文章會讓對過去學過的知識有一個新的理解,或者重溫你學習的東西,這有利於你用JavaScript實現全部交互。html

詳解事件委託

事件委託是一種由其它元素而非事件目標元素來響應事件產生的行爲的思想。用document元素來處理按鈕的點擊行爲就是事件委託的一個例子,另外一種常見狀況是,用ul元素來處理其子元素li的事件。java

有多種方法來處理事件委託。標準方法來源於原生瀏覽器的功能。瀏覽器以一種特定的工做流程來處理事件,並支持事件捕獲和事件冒泡。W3C關於瀏覽器怎麼支持事件的文檔:W3C DOM Level 3 Events。一些JS庫和框架公開了其它方式,如發佈/訂閱模型(將在後文說起)。面試

事件捕獲和事件冒泡是事件流中的兩個階段,任何事件產生時,如點擊一個按鈕,將從最頂端的容器開始(通常是html的根節點)。瀏覽器會向下遍歷DOM樹直到找到觸發事件的元素,一旦瀏覽器找到該元素,事件流就進入事件目標階段,該階段完成後,瀏覽器會沿DOM樹向上冒泡直到最頂層容器,看看是否有其它元素須要使用同一個事件。編程

下面的示例說明了這個過程。點擊按鈕會致使事件流識別自己在容器下面的文本,每個元素都接收一樣的點擊監聽代碼,因爲事件捕獲,點擊事件會首先觸發HTML節點綁定的點擊處理程序,而後在事件冒泡階段的末尾返回到最頂層元素。瀏覽器

View this on JSFiddle閉包

大多數現代庫使用冒泡監聽,而在捕獲階段處理。瀏覽器包含一個方法來管理事件冒泡。事件處理程序能夠調用stopPropagation告訴DOM事件中止冒泡,第二個方式是調用stopImmediatePropagation,它不只中止冒泡,也會阻止這個元素上其它監聽當前事件的處理程序觸發。然而,中止傳播事件時要當心,由於你不知道是否有其它上層的DOM元素可能須要知道當前事件。app

還有第三個能夠控制元素如何對事件做出迴應的方法。全部現代瀏覽器支持preventDefault方法,這個方法會阻止瀏覽器處理事件的默認行爲。一個常見示例就是連接,使用連接執行UI操做是一種常見的作法。然而,當咱們不但願連接跟普通被激活的連接同樣會在新標籤頁打開一個新頁面,就可使用preventDefault方法來阻止這個默認行爲。框架

還有其它實現事件委託的方法能夠考慮,其中值得一提的就是發佈/訂閱模型。發佈/訂閱模型也稱爲了廣播模型,牽涉到兩個參與者。一般,兩個參與者在DOM中並無緊密的聯繫,並且多是來自兄弟的容器。能夠給它們共同的祖先元素設置監聽處理程序,可是若是共同的祖先元素在DOM樹中處於較高層次(離根節點比較近),就會監聽不少同輩元素的事件,會形成意想不到的結果;固然,也可能存在邏輯或結構緣由要分開這兩個元素。dom

發佈/訂閱模型也能自定義事件。發佈/訂閱模型從一個元素髮送消息後並向上遍歷,有時也向下遍歷,DOM會通知遍歷路徑上的全部元素事件發生了。在下面的示例中,JQuery經過trigger方法傳遞事件。

View this on JSFiddle

使用事件委託來管理事件流有不少優勢,其中最大的優勢是改善性能。元素綁定的每個監聽器都會佔用一些內存,若是頁面上只有少數幾個監聽器,咱們也不會注意到它們之間的區別,而後,若是要監聽一個50行5列的表格中的每一個單元格,你的Web應用會開始變慢,爲了使應用程序最快運行的最好方式是保持儘量低的內存使用。

使用事件委託能減小監聽器數量,在元素的容器上綁定事件意味着只須要一個監聽器。這種方法的缺點是,父容器的偵聽器可能須要檢查事件來選擇正確的操做,而元素自己不會是一個監聽器。額外處理帶來的影響遠低於許多存在內存中的監聽器。

更少的監聽器和更少的DOM交互也易於維護。父容器層次的監聽器能處理多種不一樣的事件操做,這是一種簡單的方法來管理相關的事件操做,這些事件一般須要執行相關功能或須要共享數據。

若是父容器是監聽器,而後要執行獨立的內部操做而並不須要添加或者移除自己的監聽器。元素操做在單頁應用中是極其常見的,爲某部分添加一個按鈕這樣簡單的事情也會爲應用程序建立一個潛在的性能塊,沒有合適的事件委託,就必須手動爲每個按鈕添加監聽,若是每一個偵聽器不清理乾淨,它可能會致使內存泄漏。瀏覽器不會清理頁面,所以在單頁應用中,全部從內存中清理不當的碎片都會留在內存中,這些碎片會下降程序性能。

當在頁面中添加交互時,仔細考慮一下,是否真的須要去監聽元素。

另外一篇值得一讀的文章:Event Delegation In JavaScript

this在JavaScript中是怎麼工做的

this關鍵字在JavaScript中的一種經常使用方法是指代碼當前上下文。

  • 若是this沒有被設置,則默認指向全局對象,其一般是window
  • 若是一個函數中運行了一個內聯函數,好比一個事件監聽器,則this指向內聯函數的源代碼。例如,當設置一個按鈕的單擊處理程序,this將引用匿名函數內的按鈕。
  • 若是函數是一個對象的構造函數,this指向新對象。
  • 若是函數被定義在一個對象上,而後調用對象時,this指向該對象。

在異步編程中,this能夠很容易改變過程當中一個功能操做。保持處理程序上下文的一個小技巧是將其設置到閉包內的一個變量,當在上下文改變的地方調用一個函數時,如setTimeout,你仍然能夠經過該變量引用須要的對象。

 

操做this的另外一種方式是經過callapplybind。三種方法都被用於調用一個函數,並能指定this的上下文,你可讓代碼使用你規定的對象,而不是依靠瀏覽器去計算出this指向什麼。Callapplybind自己是至關複雜的,應該有本身的文檔記錄,咱們會把這當作將來待解決問題的一部分。下面是一個改變this指向方法的示例:

View this on JSFiddle

事件委託和this是現代JavaScript中重要的功能,理解它們的工做原理是成功開發產品的關鍵,而且能夠確定的是,這是應聘JavaScript工程師必需要了解的。

相關文章
相關標籤/搜索