我需要为8个对象(手掌)添加一些监听器。 这些对象是相同的,但行为必须根据其位置进行更改。 我有以下(丑陋的)代码:
root.palmsStatus = ["B","B","B","B","B","B","B","B"];
if (root.palmsStatus[0] !== "N")
root.game.palms.palm1.addEventListener("click", palmHandler = function(){ palmShakeHandler(1); });
if (root.palmsStatus[1] !== "N")
root.game.palms.palm2.addEventListener("click", palmHandler = function(){ palmShakeHandler(2); });
if (root.palmsStatus[2] !== "N")
root.game.palms.palm3.addEventListener("click", function(){ palmShakeHandler(3); });
if (root.palmsStatus[3] !== "N")
root.game.palms.palm4.addEventListener("click", function(){ palmShakeHandler(4); });
if (root.palmsStatus[4] !== "N")
root.game.palms.palm5.addEventListener("click", function(){ palmShakeHandler(5); });
if (root.palmsStatus[5] !== "N")
root.game.palms.palm6.addEventListener("click", function(){ palmShakeHandler(6); });
if (root.palmsStatus[6] !== "N")
root.game.palms.palm7.addEventListener("click", function(){ palmShakeHandler(7); });
if (root.palmsStatus[7] !== "N")
root.game.palms.palm8.addEventListener("click", function(){ palmShakeHandler(8); });
我有两个需求:
1)在点击事件中不使用匿名函数。
我写了这段代码,但它没有用
root.game.palms.palm8.addEventListener("click", palmShakeHandler(8));
所以这个工作正常
root.game.palms.palm8.addEventListener("click", function(){ palmShakeHandler(8); });
但我不明白如何删除事件监听器。 我尝试这个解决方案,但它没有工作
root.game.palms.palm8.addEventListener("click", palmHandler = function(){ palmShakeHandler(8); });
root.game.palms.palm8.removeEventListener("click", palmHandler);
2)在for循环中添加和删除监听器
我编写了以下代码,但行为不正确。
for (i=1; i <= root.palmsStatus.length; i++){
if (root.palmsStatus[i-1] !== "N"){
root.game.palms["palm" + i].addEventListener("click", function(){ palmShakeHandler(i); });
}
}
添加了侦听器,但传递给 palmShakeHandler 的参数值始终为8。
没人能帮我解决这些问题?
答案 0 :(得分:4)
使用Function.prototype.bind
方法在JavaScript中实际上有一种完美的方法。
bind
允许您定义将作为参数传递的额外参数。
您还应该记住bind
创建一个新函数,而不是修改初始函数。
这是它的样子:
function palmHandler(number) {
// your code working with `number`
}
var palmHandler8 = palmHandler.bind(null, 8)
// the palmHandler8 is now tied to the value 8.
// the first argument (here null) define what `this` is bound to in this function
这应该可以解决您的问题,并且您可以轻松删除处理程序:)
您的代码如下所示:
for (i=1; i <= root.palmsStatus.length; i++){
if (root.palmsStatus[i-1] !== "N"){
root.game.palms["palm" + i].addEventListener("click", palmShakeHandler.bind(null, i));
}
}
为了能够在之后删除处理程序,您需要保留对使用bind
创建的函数的引用。这将是这样做的方式。
var boundHandler = handler.bind(null, i);
element.addEventListener(boundHandler);
element.removeEventListener(bounderHander);
如果您想了解更多有关JavaScript中令人敬畏的bind
方法的信息,那么MDN就是您的朋友:) https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_objects/Function/bind
8
的问题是JavaScript中一个非常常见的问题。这个主题将解释一切(剧透,这是一个范围问题:))https://stackoverflow.com/a/750506/2745879
答案 1 :(得分:0)
在你的上一个解决方案中,你正在为每个函数提供相同的var,这就是使函数与8一起工作的原因,因为它是变量的最后一个值。
要工作arround,你可以使用“let”(请至少使用var,其他人认为“i”是全局的,并且可以在代码中的每个位置更改)但是因为我不知道你的目标浏览器我建议其他解决方案
for (var i=1; i <= root.palmsStatus.length; i++){
if (root.palmsStatus[i-1] !== "N"){
root.game.palms["palm" + i].addEventListener("click", (function(index)
(return function(){
palmShakeHandler(index);
}))(i);
}
}
由于它看起来像是针对现代浏览器,我将使用let。https://kangax.github.io/compat-table/es6/
for (var i=1; i <= root.palmsStatus.length; i++){
let index = i;
let intermediateFunction = function(){palmShakeHandler(index);};
if (root.palmsStatus[i-1] !== "N"){
root.game.palms["palm" + i].addEventListener("click",intermediateFunction);
root.game.palms["palm" + i].removeHandShake = function(){this.removeEventListener("click",intermediateFunction)};
}
}
所以现在你只需要调用“removeHandShake”并删除监听器
我这里有代码,所以它可以轻松弹出一些小错误
答案 2 :(得分:0)
因此,如果你的“手掌”阵列非常庞大,那么为每个人添加一个事件监听器基本上是一个坏主意,因为这会导致性能缺陷。所以我建议采用不同的方法:
var handlers = [function (e) {}, …, function (e) {}];
root.game.palms.forEach(functiion (palm, idx) {
palm.setAttribute('data-idx', idx);
});
<palmsparent>.addEventListener('click', function (e) {
var c = e.target, idx = -1;
while (c) {
if (c.hasAttribute && c.hasAttribute('data-idx')) {
idx = parseInt(c.getAttribute('data-idx'));
break;
}
c = c.parentNode;
}
//here you also check for the »palm status«
if (idx >= 0) {
handlers[idx](c);
}
})
一个事件监听器,更容易删除,更好的性能。