js也可以有自訂事件 注入就是這麼爽

來源:互聯網
上載者:User
js

  在c#中有delegate,還有特殊的可以直接應用於事件編程的delegate,那就是event。而在js中沒有c#的event,更沒有delegate,有的只是dom元素內建的的native的不可擴充的event,比如無法為input元素添加事件,只能在其擁有的事件(如onclick=handler)上擴充應用。那麼能不能做到自訂的事件類比效果呢?答案是肯定的,也就是本文的主題。
  首先弄明白一下事件的意圖——可以在發生一件事的時候執行額外的代碼,如document.attachEvent('onclick', function(){alert('u click document')}),當點擊頁面時(事件發生了),就會執行我們為其掛接的其它代碼(js中以function為語句集合,以下稱為function),當然我們可以在一個事件上掛接任意多的function,這樣就實現了一種靈活的可擴充編程介面。試想如果可以像在元素事件擴充應用一樣可以在任意對象的任意方法上擴充,那對於js編程來講就更加靈活了。先看一個例子,平時我們把相對對立的一個功能命名為一個function,並在需要的地方(通常是另一個function)調用以實現代碼複用:
function F(){
    this.method = function(){
        alert('f.method is called')
        g();
    }
}
function g(){
    alert(123)
}
var f = new F();
f.method()


我們把f.method中直接調用g改寫一下,封裝到一個Event對象中達到一樣的效果,代碼如下:
var Event = {
    __list:[],
    observe:function(obj, ev, fun){
        this.__list.push({o:obj, e:ev, f:fun})
    },
    occor:function(obj, method){
        var arr = []
        for(var i=0; i<this.__list.length; i++){
            if(this.__list[i].o==obj && this.__list[i].e==method) arr.push(this.__list[i]);
        }
        for(var i=0; i<arr.length; i++){
            arr[i].f();
        }
    }
}

function F(){
    this.method = function(){
        alert('f.method is called')
        Event.occor(this, 'method');
    }
}

var f = new F();
Event.observe(f, 'method', function(){alert(123)})
f.method()這樣乍看上去好像費了“太多”功夫,但卻把“在f中調用g的寫法”更通用化了,如果要在f中調用h則只需要多些一行Event.occor(this, 'methodName'),寫到這裡你肯定也注意到methodName的寫法和最開始的寫法是一樣的,都是硬編的不具靈活性,如果在每個類的方法中都寫入Event.occor(this, 'method')就太不雅觀了,也背離了我們的初衷,動態修改一下method把它加到最後一行就ok了,下一步就是解決它,改進代碼如下:

var Event = {
    __list:[],
    observe:function(obj, ev, fun){
        this.__list.push({o:obj, e:ev, f:fun})
    },
    occor:function(obj, method){
        var arr = []
        for(var i=0; i<this.__list.length; i++){
            if(this.__list[i].o==obj && this.__list[i].e==method) arr.push(this.__list[i]);
        }
        for(var i=0; i<arr.length; i++){
            arr[i].f();
        }
    },
    inject:function(obj){
        for(var p in obj){
            obj[p] = new Function(obj[p].toString().replace('function(){', '').replace('}', 'Event.occor(this,p)'))
        }
    }
}

function F(){
    this.method = function(){
        alert('f.method is called')
    }
}

var f = new F();
Event.inject(f);
Event.observe(f, 'method', function(){alert(123)})
f.method()我們把顯示的在被呼叫者法體內調用Event.occor改寫到Event.inject中。到此我們就簡單(還有一些安全的程式碼沒有處理,如沒有判斷obj[p]是否需要被改寫、沒有測試效率問題,沒有處理更多添加Event.occor時的邏輯判斷,下一步準備把它實現為一個Observeable對象,就更加靈活了)的完成了自訂事件。



相關文章

Beyond APAC's No.1 Cloud

19.6% IaaS Market Share in Asia Pacific - Gartner IT Service report, 2018

Learn more >

Apsara Conference 2019

The Rise of Data Intelligence, September 25th - 27th, Hangzhou, China

Learn more >

Alibaba Cloud Free Trial

Learn and experience the power of Alibaba Cloud with a free trial worth $300-1200 USD

Learn more >

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。