简体   繁体   English

在forEach循环中使用带有参数的函数

[英]Using a Function with a Parameter inside a forEach Loop

In an attempt to make my code drier, I've decided to take an if/else statement that I use often and turn it into a function. 为了让我的代码更干燥,我决定采用我经常使用的if / else语句并将其转换为函数。 I tried applying this function to a forEach loop, however, I am getting an error that the function's parameter is undefined. 我尝试将此函数应用于forEach循环,但是,我收到一个错误,函数的参数未定义。

Here's the code: 这是代码:

var addClass = (className) => {
    (this.classList.contains(className) === true)
        ? this.classList.remove('active') & this.classList.add(className)
        : this.classList.add(className);
}

exploreStory_buttons.forEach(el => el.addEventListener('mouseover'), addClass(active));

Any insight into what I'm doing wrong would be greatly appreciated. 任何洞察我做错的事情都将不胜感激。 As per usual, I feel as though the solution may be simple: that I'm just not seeing it. 按照惯例,我觉得解决方案可能很简单:我只是没有看到它。

You want to call the function in the proper context. 您想在适当的上下文中调用该函数。 There is Function#call for that purpose. 为此目的有Function#call You also need to use a normal function, as "fat arrow" functions handle this differently. 您还需要使用普通函数,因为“胖箭头”函数可以不同地处理this

var addClass = function (className) {
    if (this.classList.contains(className)) {
        this.classList.remove('active');
        this.classList.add(className);
    } else {
        this.classList.add(className);
    }
}

exploreStory_buttons.forEach(el => {
    el.addEventListener('mouseover'); // where is the event listener??
    addClass.call(this, active);   // N.B. active is undefined here. Do you mean "active"?
});

You also do not want to abuse language features to write "smart" code. 您也不想滥用语言功能来编写“智能”代码。 Use if/else and multiple lines for multiple statements, you are not a code obfuscator. 对多个语句使用if / else和多行,您不是代码混淆器。


Assuming you want to add a "hover" behavior, the code would have look something like this: 假设您要添加“悬停”行为,代码看起来像这样:

function addClass(className) {
    return function () {
        this.classList.add(className);
    }
}
function removeClass(className) {
    return function () {
        this.classList.remove(className);
    }
}

var activate = addClass('active');
var deactivate = removeClass('active');

exploreStory_buttons.forEach(el => {
    el.addEventListener('mouseenter', activate);
    el.addEventListener('mouseleave', deactivate);
});

Note how addClass and removeClass return functions that can serve as event handlers. 请注意addClassremoveClass如何返回可用作事件处理程序的函数。 Storing them into activate and deactivate variables means you are not creating multiple equivalent copies of a function inside the loop, but in fact assign the same function to all elements. 将它们存储到activatedeactivate变量意味着您不是在循环内创建函数的多个等效副本,而是实际上为所有元素分配相同的函数。


The activate / deactivate variables and function-returning functions can be avoided by implementing a hover() function (jQuery has a similar feature ): 通过实现hover()函数可以避免activate / deactivate变量和函数返回函数(jQuery具有类似的功能 ):

function hover(elements, onenter, onleave) {
    elements.forEach(el => {
        el.addEventListener('mouseenter', onenter);
        el.addEventListener('mouseleave', onleave);
    });
}

hover(exploreStory_buttons, function () {
    this.addClass('active');
}, function () {
    this.removeClass('active');
});

Here the event handler functions are created only once and directly where they are needed. 这里,事件处理函数只创建一次,直接在需要它们的地方创建。 Much better than storing them in helper variables. 比将它们存储在辅助变量中要好得多。

There are several issues with your code: 您的代码有几个问题:

  1. I assume that on mouseover you would like to change the class of the element to active. 我假设在mouseover你想将元素的类更改为活动状态。 In this case addClass function has to return another function, but regular one, not fat arrow, so this can be properly bound. 在这种情况下, addClass函数必须返回另一个函数,但是常规函数,而不是胖箭头,因此可以正确绑定。
  2. Did you really wanted bitwise AND on this line: 你真的想在这一行上按位AND:

    this.classList.remove('active') & this.classList.add(className)

or logical AND? 或逻辑AND?

 exploreStory_buttons = document.getElementsByClassName('explore-story'); var addClass = (className) => function() { this.classList.contains(className) ? (this.classList.remove('active') && this.classList.add(className)) : this.classList.add(className); } Array.prototype.forEach.call(exploreStory_buttons, (el) => el.addEventListener('mouseover', addClass.call(el, 'active'))); 
 .active { color: red } 
 <button class="explore-story active">Story 1</button> <button class="explore-story">Story 2</button> 

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM