【问题标题】:JSHint warning about closures inside loops using outer variablesJSHint 关于使用外部变量的循环内部闭包的警告
【发布时间】:2017-09-30 20:13:45
【问题描述】:

我的代码确实有效,但我不想再出现 jshint 错误:

在循环中声明的函数引用外部作用域变量可能会导致语义混乱

  1. 我已经尝试使用 ES6 中的 let 来解决该错误,因为我认为这可以解决问题。我也将 gruntfile 配置为使用 ES6。

  2. 我尝试使用两个循环,带有变量“i”的外循环和带有变量“j”的内循环

都没有用。

此处提供完整代码:https://jsfiddle.net/rwschmitz/zz7ot3uu/

var hobbies = document.getElementsByClassName("hobbies");
var active = false;

// For mouse input

for (var i = 0; i < 5; i++) {
    hobbies[i].onmouseover = function() {
            hobbies[0].classList.add('hobbies-slide-left');
            hobbies[1].classList.add('hobbies-slide-right');
            hobbies[2].classList.add('hobbies-slide-left');
            hobbies[3].classList.add('hobbies-slide-right');
            hobbies[4].classList.add('hobbies-slide-left');
    };
}

// For click input

for (var i = 0; i < 5; i++) {
    hobbies[i].onclick = function() {
            hobbies[0].classList.add('hobbies-slide-left');
            hobbies[1].classList.add('hobbies-slide-right');
            hobbies[2].classList.add('hobbies-slide-left');
            hobbies[3].classList.add('hobbies-slide-right');
            hobbies[4].classList.add('hobbies-slide-left');
    };
}

【问题讨论】:

    标签: javascript loops closures jshint


    【解决方案1】:

    您可以使用Array#forEach() 将您的循环更改为这样的:

    var hobbies = Array.from(document.getElementsByClassName('hobbies'));
    var classes = ['hobbies-slide-left', 'hobbies-slide-right'];
    var events = ['mouseover', 'click'];
    
    function addHobbyClass (hobby, index) {
      hobby.classList.add(this[index % this.length]);
    }
    
    function hobbyEventListener () {
      hobbies.forEach(addHobbyClass, classes);
    }
    
    hobbies.forEach(function (hobby) {
      this.forEach(function (event) {
        this.addEventListener(event, hobbyEventListener);
      }, hobby);
    }, events);
    

    【讨论】:

    • 是的,这行得通。我必须在适当的地方添加 7 个分号。我对 StackOverflow 有点陌生。所以我不确定这是否值得编辑你的答案。无论如何,代码仍然适用于您的解决方案并消除错误。我会标记为已接受。谢谢!
    • 哦,我使用了另一个名为 standard 的 linter。它实际上本身并不是一个标准,但它包含 JavaScript 的 ASI 规则(自动分号插入)。由于这个问题专门针对 linting,如果您愿意,我可以将它们添加回来。
    • 我会说严格把它们加回来,因为它是关于 JSHint 的主题。不管怎样,你回答得这么快真是太棒了,我真的很感激你!
    • @rudolphschmitz 完成,祝你的项目代码标准化,这是一个很好的做法。
    【解决方案2】:

    关于如何解决问题的另外两个示例。

    var hobbies = document.querySelectorAll('.hobbies');
    var eventHooks = ['mouseover', 'click'];
    
    hobbies.forEach(function(hobby) {
      eventHooks.forEach(function(hook) {
        hobby.addEventListener(hook, function() {
          hobbies[0].classList.add('hobbies-slide-left');
          hobbies[1].classList.add('hobbies-slide-right');
          hobbies[2].classList.add('hobbies-slide-left');
          hobbies[3].classList.add('hobbies-slide-right');
          hobbies[4].classList.add('hobbies-slide-left');
        });
      });
    });

    var hobbies = document.getElementsByClassName('hobbies');
    var eventHooks = ['mouseover', 'click'];
    
    // Attach events
    var attachEvents = function(key) {
      eventHooks.forEach(function(hook) {
        hobbies[key].addEventListener(hook, function() {
          hobbies[0].classList.add('hobbies-slide-left');
          hobbies[1].classList.add('hobbies-slide-right');
          hobbies[2].classList.add('hobbies-slide-left');
          hobbies[3].classList.add('hobbies-slide-right');
          hobbies[4].classList.add('hobbies-slide-left');
        });
      });
    };
    
    // Init
    var init = function() {
      // Loop through hobbies
      for (var i = 0; i < hobbies.length; i++) {
        attachEvents(i);
      }   
    }
    
    init();

    【讨论】:

    • 由于这是关于 linting,我也会尝试使用非 DRY 代码(hobbies[hardcodedNumberLiteral].classList.add(hardcodedString))解决问题,类似于您解决 eventHooks 的方式。如果您不介意,我实际上想将其包含在我的答案中。
    • @PatrickRoberts 是的!在您的示例中添加类要干净得多。
    • 感谢您提供多种解决方案!看来我需要更加熟悉 forEach 方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-31
    • 1970-01-01
    • 1970-01-01
    • 2015-11-14
    • 1970-01-01
    • 2014-05-01
    相关资源
    最近更新 更多