114

我想做一个eventHandler传递事件和一些参数的。问题是该函数没有获取元素。这是一个例子:

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);
}
4

8 回答 8

119

我不完全了解您的代码要做什么,但是您可以利用函数闭包的优势在任何事件处理程序中使变量可用:

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);
}

根据您的确切编码情况,您几乎总是可以使某种闭包保留对变量的访问。

根据您的评论,如果您要完成的是:

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在匿名函数中包装代码

JavaScript 中的立即调用函数表达式 (IIFE) - 传递 jQuery

JavaScript 自执行匿名函数有哪些好的用例?

最后一个版本可能更容易看到它在做什么:

// 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));
于 2012-04-03T19:41:07.750 回答
39

这是一个古老的问题,但却是一个普遍的问题。所以让我在这里添加这个。

使用箭头函数语法,您可以更简洁地实现它,因为它是词法绑定的并且可以链接。

箭头函数表达式是正则函数表达式的语法紧凑替代方案,尽管它没有绑定到 this、arguments、super 或 new.target 关键字。

const event_handler = (event, arg) => console.log(event, arg);
el.addEventListener('click', (event) => event_handler(event, 'An argument'));

如果需要清理事件监听器:

// Let's use use good old function sytax
function event_handler(event, arg) {
  console.log(event, arg);
}

// Assign the listener callback to a variable
var doClick = (event) => event_handler(event, 'An argument'); 

el.addEventListener('click', doClick);

// Do some work...

// Then later in the code, clean up
el.removeEventListener('click', doClick);

这是疯狂的单线:

// You can replace console.log with some other callback function
el.addEventListener('click', (event) => ((arg) => console.log(event, arg))('An argument'));

更温顺的版本:更适合任何理智的工作。

el.addEventListener('click', (event) => ((arg) => {
  console.log(event, arg);
})('An argument'));
于 2018-02-27T18:40:54.610 回答
9

您可以尝试使用 bind 方法,我认为这可以实现您的要求。如果没有别的,它仍然非常有用。

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);
于 2015-01-05T13:54:51.723 回答
2

鉴于对原始问题的更新,似乎在传递事件处理程序时上下文(“this”)存在问题。这里解释了基础知识,例如 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()?

于 2016-06-16T08:48:18.933 回答
2

简短的回答:

x.addEventListener("click", function(e){myfunction(e, param1, param2)});

... 

function myfunction(e, param1, param1) {
    ... 
} 
于 2018-12-31T09:57:51.007 回答
1

尝试,

const handleOnChange = (event, otherParameter) => {
    console.log(`${event.target.value}`);
    console.log(`${otherParameter}`);
}

<Select onchange= (event) => {
    handleOnChange(event, otherParameter);
}>
于 2021-07-04T09:27:17.953 回答
0

this里面doThings是窗口对象。试试这个:

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

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

    return {
        eventHandler: eventHandler
    };
};
于 2012-04-03T19:50:19.740 回答
-2
let obj = MyObject();

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

//calls the MyObject.func, passing the param.
于 2016-11-16T13:30:04.680 回答