如何使用addEventListener向函数传递参数?

74

在传统的添加事件监听器的方法中:

function getComboA(sel) {
    var value = sel.options[sel.selectedIndex].value;  
}

<select id="comboA" onchange="getComboA(this)">
<option value="">Select combo</option>
<option value="Value1">Text1</option>
<option value="Value2">Text2</option>
<option value="Value3">Text3</option>
</select>

但是我想要适应使用addEventListener的方式:

productLineSelect.addEventListener('change',getSelection(this),false);

function getSelection(sel){
    var value = sel.options[sel.selectedIndex].value;
    alert(value);
}

为什么我不能在addEventListener方法中传递参数给getSelection()作为第二个参数呢?据我所知,我只能使用函数名称而不需要括号。

有什么想法吗?

顺便提一下,请看看我的以前的问题,关于console.log无法在Safari 6.0开发人员检查器中输出,这让我很沮丧。


可能是将额外的参数传递给回调函数的重复问题。 - Michał Perłakowski
4个回答

145

不需要传递任何参数。用于addEventListener的函数将自动绑定this到当前元素。只需在您的函数中使用this

productLineSelect.addEventListener('change', getSelection, false);

function getSelection() {
    var value = this.options[this.selectedIndex].value;
    alert(value);
}

这里是示例代码:http://jsfiddle.net/dJ4Wm/


如果想要向函数传递任意数据,可以将其包装在匿名函数调用中:

productLineSelect.addEventListener('change', function() {
    foo('bar');
}, false);

function foo(message) {
    alert(message);
}

以下是示例代码:http://jsfiddle.net/t4Gun/


如果你想手动设置this的值,你可以使用 call方法来调用该函数:

var self = this;
productLineSelect.addEventListener('change', function() {
    getSelection.call(self);
    // This'll set the `this` value inside of `getSelection` to `self`
}, false);

function getSelection() {
    var value = this.options[this.selectedIndex].value;
    alert(value);
}

1
太好了!完美的答案!你能指出JavaScript中将函数名(我的意思是没有括号)传递给其他函数的机制吗?这对我来说真的很有趣。 - mko
3
宝贵的回答。 - kta
8
在您的第二个示例中,您如何删除该事件侦听器?该函数是匿名的。 - jkupczak
我喜欢你在第二个例子中通过将参数包装在匿名函数中来传递参数的想法,但还有其他方法吗?类似于OP在他的问题中发布的内容? - Praneet Dixit

15
在你的JS代码的第一行:
select.addEventListener('change', getSelection(this), false);

你正在通过在函数引用后面放置(this)来调用getSelection。这很可能不是你想要的,因为你现在传递的是该调用的返回值,而不是实际函数本身的引用。
在由addEventListener调用的函数中,this的值将自动设置为侦听器所附加到的对象,在此示例中为productLineSelect
如果这正是您想要的,您可以仅传递函数引用,并且在从addEventListener调用时,this将在此示例中是select
select.addEventListener('change', getSelection, false);

如果这不是你想要的,最好将此值 bind 到传递给 addEventListener 函数的函数中:

var thisArg = { custom: 'object' };
select.addEventListener('change', getSelection.bind(thisArg), false);

"

.bind部分也是一个调用,但这个调用只返回我们正在调用bind的相同函数,其中函数范围内this的值被固定thisArg,有效地覆盖了动态绑定的性质。

"
为了回答你的问题:"如何在addEventListener中传递参数?" 你需要使用额外的函数定义:
var globalVar = 'global';

productLineSelect.addEventListener('change', function(event) {
    var localVar = 'local';
    getSelection(event, this, globalVar, localVar);
}, false);

现在我们将事件对象、对于addEventListener回调函数内部this值的引用、在该回调函数中定义和初始化的变量以及整个addEventListener调用外部的一个变量传递给你自己编写的getSelection函数。请注意保留HTML标签。

我们也可能再次选择一个对象作为外部回调函数中的this:

var thisArg = { custom: 'object' };
var globalVar = 'global';

productLineSelect.addEventListener('change', function(event) {
    var localVar = 'local';
    getSelection(event, this, globalVar, localVar);
}.bind(thisArg), false);

1
谢谢Jeffrey Westerkamp,你的回答很有帮助,因为你详细地解释了它! - Yone
这个答案似乎是最好的,但可以通过提到创建绑定版本会创建一个“新”函数来改进。将其保存在变量中并传递该函数还将允许使用removeEventListener。更多信息请参见@bens的答案:https://dev59.com/Omgu5IYBdhLWcg3wHjl7 - pietervanderstar

7

当您使用addEventListener时,this会自动绑定。因此,如果您想要一个对安装了事件处理程序的元素的引用,只需在函数内部使用this

productLineSelect.addEventListener('change',getSelection,false);

function getSelection(){
    var value = sel.options[this.selectedIndex].value;
    alert(value);
}

如果您想从调用addEventListener的上下文中传入其他参数,可以使用闭包,例如:

productLineSelect.addEventListener('change', function(){ 
    // pass in `this` (the element), and someOtherVar
    getSelection(this, someOtherVar); 
},false);

function getSelection(sel, someOtherVar){
    var value = sel.options[sel.selectedIndex].value;
    alert(value);
    alert(someOtherVar);
}

3
如果你想要的 this 值就是绑定事件处理程序的对象,那么 addEventListener() 已经为你做到了这一点。当你这样做时:
productLineSelect.addEventListener('change', getSelection, false);

getSelection 函数将已经被调用,并且 this 已经设置为绑定事件处理程序的对象。它还将传递一个表示事件对象的参数,其中包含有关事件的各种对象信息。

function getSelection(event) {
    // this will be set to the object that the event handler was bound to
    // event is all the detailed information about the event
}

如果所需的this值不是绑定事件处理程序的对象,而是其他值,则可以执行以下操作:

var self = this;
productLineSelect.addEventListener('change',function() {
    getSelection(self)
},false);

解释一下:

  1. 你将this的值保存到其他事件处理程序的本地变量中。
  2. 然后创建一个匿名函数来传递给addEventListener。
  3. 在该匿名函数中,调用实际函数并传递保存的this的值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接