2012-04-03 57 views
46

我想創建一個eventHandler來傳遞事件和一些參數。問題是該函數沒有得到該元素。以下是一個示例:帶參數的Javascript事件處理程序

doClick = function(func){ 
    var elem = .. // the element where it is all about 
    elem.onclick = function(e){ 
     func(e, elem); 
    } 
} 
doClick(function(e, element){ 
    // do stuff with element and the event 
}); 

'elem'必須在匿名函數之外定義。我怎樣才能獲得傳遞的元素在匿名函數內使用?有沒有辦法做到這一點?

那麼addEventListener呢?我似乎無法通過addEventListener傳遞事件嗎?

更新

我似乎和解決問題「這個」

doClick = function(func){ 
    var that = this; 
    this.element.onclick = function(e){ 
     func(e, that); 
    } 
} 

如果這包含this.element,我可以在函數訪問。

使用addEventListener

但我不知道有關的addEventListener:

function doClick(elem, func){ 
    element.addEventListener('click', func(event, elem), false); 
} 
+1

你有ELEM,元素,參與你的問題的元素。你能減少混淆嗎? – mihai 2012-04-03 19:44:22

+0

對不起,我試圖舉出一個我的情況的例子,但是這樣做並不順利,我更新了代碼。 – sebas2day 2012-04-03 19:54:33

+0

您是否在尋找'e.target' /'e.currentTarget'? – Rolf 2015-12-17 10:08:07

回答

56

我不明白到底是什麼你的代碼是試圖做的,但你可以在任何可用的變量使用功能閉包的優點的事件處理程序:

function addClickHandler(elem, arg1, arg2) { 
    elem.addEventListener('click', function(e) { 
     // in the event handler function here, you can directly refer 
     // to arg1 and arg2 from the parent function arguments 
    }, false); 
} 

根據您的確切編碼si你幾乎總是可以做某種閉包來保存對你的變量的訪問權限。

從您的意見,如果你想實現什麼是這樣的:

element.addEventListener('click', func(event, this.elements[i])) 

然後,您可以用捕獲在一個封閉,只要你想的參數自執行的函數(IIFE)做到這一點它執行和返回實際的事件處理函數:

element.addEventListener('click', (function(passedInElement) { 
    return function(e) {func(e, passedInElement); }; 
}) (this.elements[i]), false); 

有關的IIFE是如何工作的,看到這些其他引用的詳細信息:

Javascript wrapping code inside anonymous function

Immediately-Invoked Function Expression (IIFE) In JavaScript - Passing jQuery

What are good use cases for JavaScript self executing anonymous functions?

這最後一個版本或許更容易看到它在做什麼這樣的:

// return our event handler while capturing an argument in the closure 
function handleEvent(passedInElement) { 
    return function(e) { 
     func(e, passedInElement); 
    }; 
} 

element.addEventListener('click', handleEvent(this.elements[i])); 

也可以使用.bind()將參數添加到回調。您傳遞給.bind()的任何參數都將被添加到回調本身所具有的參數中。所以,你可以這樣做:

elem.addEventListener('click', function(a1, a2, e) { 
    // inside the event handler, you have access to both your arguments 
    // and the event object that the event handler passes 
}.bind(elem, arg1, arg2)); 
+0

是的,這幾乎是我想要做的,但是如果匿名函數作爲參數通過addClickHandler傳遞並且您想要爲此函數提供一些參數,例如:element.addEventListener('click',func(event ,this.elements [i])); – sebas2day 2012-04-03 20:00:57

+2

@ sebas2day - 你不能做'element.addEventListener('click',func(event,this.elements [i]))''。 JavaScript只是不這樣工作。還有其他方法,使用閉包,但是你不能像你寫的那樣去做。 addEventListener只用一個參數(事件)調用它的回調函數,並且不能以任何方式改變它。 – jfriend00 2012-04-03 20:39:24

+0

我在我的回答結尾添加了另一個這樣做的例子。 – jfriend00 2012-04-03 20:47:23

0

thisdoThings內是window對象。試試這個:

var doThings = function (element) { 
    var eventHandler = function(ev, func){ 
     if (element[ev] == undefined) { 
      return; 
     } 

     element[ev] = function(e){ 
      func(e, element); 
     } 
    }; 

    return { 
     eventHandler: eventHandler 
    }; 
}; 
6

你可以嘗試的東西是使用綁定方法,我認爲這實現了你所要求的。如果沒有別的,它仍然非常有用。

function doClick(elem, func) { 
    var diffElem = document.getElementById('some_element'); //could be the same or different element than the element in the doClick argument 
    diffElem.addEventListener('click', func.bind(diffElem, elem)) 
} 

function clickEvent(elem, evt) { 
    console.log(this); 
    console.log(elem); 
    // 'this' and elem can be the same thing if the first parameter 
    // of the bind method is the element the event is being attached to from the argument passed to doClick 
    console.log(evt); 
} 

var elem = document.getElementById('elem_to_do_stuff_with'); 
doClick(elem, clickEvent); 
2

鑑於更新原來的問題,好像有與上下文的麻煩(「本」),同時通過事件處理程序。 基本知識解釋如這裏 http://www.w3schools.com/js/js_function_invocation.asp

的例子簡單的工作版本可以讀取

var doClick = function(event, additionalParameter){ 
    // do stuff with event and this being the triggering event and caller 
} 

element.addEventListener('click', function(event) 
{ 
    var additionalParameter = ...; 
    doClick.call(this, event, additionalParameter); 
}, false); 

參見 Javascript call() & apply() vs bind()?

-1
let obj = MyObject(); 

elem.someEvent(function(){ obj.func(param) }); 

//calls the MyObject.func, passing the param. 
+0

這是如何解決OP的問題的? – RamenChef 2016-11-16 13:54:46

+0

param也可以是一個回調函數(在-say-全局上下文中),因此可以很容易地回調,並且具有所請求的參數。 – 2016-11-16 17:18:39

1

這是一個老問題,但常見的一種。所以讓我在這裏添加一個。

有了ES2015語法就可以實現更簡潔的方式:

function event_handler(event, arg) { 
    console.log(event, arg); 
} 

element.addEventListener('click', (event) => event_handler(event, 'Here comes the argument'));