更有效的方式在两个事件监听器之间交替?

时间:2013-11-08 06:55:23

标签: javascript

我会尽量保持简短。我在两个事件监听器之间交替,一个叫“goMetric”,另一个叫“goImperial”。 unitSwitch是在两者之间切换的链接。是否有更有效的方法来删除一个事件侦听器并将其替换为另一个事件侦听器?关于如何编写更好代码的任何其他提示都非常感谢。

(注意:我现在正试图避免使用jQuery,以便更好地理解JavaScript。我想了解引擎盖下的内容。)

var isMetric = false;
unitSwitch.addEventListener('click', goMetric);

function goMetric() {
    isMetric = true;
    // removed other code
    unitSwitch.innerHTML = "Go imperial";
    unitSwitch.removeEventListener('click', goMetric);
    unitSwitch.addEventListener('click', goImperial);
}

function goImperial() {
    isMetric = false;
    // removed other code
    unitSwitch.innerHTML = "Go metric";
    unitSwitch.removeEventListener('click', goImperial);        
    unitSwitch.addEventListener('click', goMetric);
}

看起来像很多代码来做这么简单的事情。

3 个答案:

答案 0 :(得分:4)

IMO更好的方法是使用单个侦听器并合并两个

function toggleMetricImperial() {
    isMetric = !isMetric;
    unitSwitch.innerHTML = isMetric ? "Go Imperial" : "Go Metric";
    ... other code ...
}

但是要删除一个侦听器并设置另一个侦听器,是的,您需要删除一个侦听器并设置另一个侦听器: - )

如果这在您的代码中非常常见,那么您可以在像

这样的库中分解出这种需求
function switcher(first, second) {
   var which = second;
   return function() {
       which = (which == first ? second : first);
       return which.apply(null, arguments);
   }
}

因此,通过将听众设置为switcher(goImperial, goMetric),您可以得到您想要的内容。当然,在这种情况下,设置按钮标题将是“......其他代码...”部分的一部分。

switcher是一个被称为高阶函数,给定两个函数返回一个函数,当被调用时会调用一个或另一个交替它们。请注意,给定this的Javascript规则,您可能需要将处理程序包装在调用处理程序主体的函数中,并传递正确的this。例如,在Javascript中,调用obj.meth();var m=obj.meth; m();不同。

答案 1 :(得分:3)

我会这样写:

var isMetric = false;
unitSwitch.addEventListener('click', onClick);

function onClick()
{
    isMetric = !isMetric;
    unitSwitch.innerHTML = (isMetric ? "Go metric" : "Go imperial");
}

不需要两个不同的事件处理程序来进行状态依赖操作。

答案 2 :(得分:2)

尝试这样简单的事情......这只需要一个侦听器,分配给处理切换逻辑的静态函数。 rcpaul 提到了类似的东西,但是都是速记形式。

var isMetric = false;
unitSwitch.addEventListener('click', toggleUnit);

function goMetric() {
    isMetric = true;
    unitSwitch.innerHTML = "Go imperial";
}

function goImperial() {
    isMetric = false;
    unitSwitch.innerHTML = "Go metric";      
}

function toggleUnit() {
    if (isMetric) {
        goImperial();
    } else {
        goMetric();
    }
}

// Init
goMetric();