代码之家  ›  专栏  ›  技术社区  ›  Michael La Voie Frederik Gheysels

RequireJs在组合文件时打破了我的for循环(r.js)

  •  0
  • Michael La Voie Frederik Gheysels  · 技术社区  · 7 年前

    我正在使用RequireJs和用于生产版本的r.js来组合/缩小和丑化它,但遇到了一个与它如何处理我的一个for循环有关的bug。

    我关闭了r.js构建上的所有优化,所以现在它只将代码合并到一个文件中,而不是缩小/隐藏;但是,该错误仍然存在。

    原始(简化)代码:

    var myArray = ['item1', 'apple', 'item2', 'item3', 'bread', 'etc'];
    
    //remove items from array according to some complex logic
    for (var i = 0; i < myArray.length; i++) {
    
      var cur = myArray[i];
    
      if (cur.indexOf('item') === 0) { //if starts with "item" remove it
        myArray.splice(i, 1);
        i--; //*IMPORTANT* Move index back to avoid skipping next item
        continue;
      }
    
      //do unrelated processing
    }
    
    //now use the array
    alert(myArray);
    

    原始代码输出:

    ['apple', 'bread', 'etc']
    

    此代码按编写的方式正常工作。然而,当我通过r.js运行它时(使用optimize:“none”),它输出的代码并没有按预期工作:

    r、 js输出代码:

    var myArray = ['item1', 'apple', 'item2', 'item3', 'bread', 'etc'];
    
    
    var _loop = function _loop(_i) {
      var cur = myArray[_i];
    
      if (cur.indexOf('item') === 0) {
        myArray.splice(_i, 1);
        _i--;
        return 'continue';
      }
    }
    
    for (var i = 0; i < myArray.length; i++) {
      var _ret = _loop(i);
    
      if (_ret === 'continue') continue;
    }
    
    alert(myArray);
    

    r、 js代码输出:

    ['apple', 'item3', 'bread', 'etc']
    

    正如您所看到的,代码是 几乎 相同,但由于r.js将我的for循环移动到了一个函数中,我无法更改索引,因此在删除/拼接一个值并向后移动索引后,对索引的更改将完全丢失,并跳过数组中的下一项。

    工作环境

    我可以前后循环索引,这样就不需要更改索引,但我正在执行其他需要按顺序(前后)进行的计算。另外,我担心这个bug将来会潜入我的代码中。

    问题

    这就是r.js的工作原理吗(我是否错过了一个简单的设置)?

    我是否以反模式编码,是否应该改变我的方法?

    谢谢

    1 回复  |  直到 7 年前
        1
  •  0
  •   JJWesterkamp    7 年前

    使现代化

    正如评论中所讨论的,解决方案是 i 超出 for 回路结构:

    var i;
    for (i = 0; i < myArray.length; i++) {
        // ...
    }
    

    意见:自 there is no functional difference 在两种声明方式之间 ,有趣的是,r.js将它们解释为不同的。


    你当然也可以 Array.prototype.filter 要完全回避问题:

    var myArray = ['item1', 'apple', 'item2', 'item3', 'bread', 'etc'];
    myArray = myArray.filter(item => ! /^item/.test(item));
    console.log(myArray);

    还可以在过滤之前和之后使用 Array.prototype.forEach :

    var myArray = ['item1', 'apple', 'item2', 'item3', 'bread', 'etc'];
    
    /** @return {boolean} */
    function filterFn(item, index) {
      console.log(`Doing additional stuff with: myArray[${index}] = ${item}`);
      return ! /^item/.test(item);
    }
    
    myArray = myArray.filter(filterFn);
    
    myArray.forEach((item, index) => {
      console.log(`After: myArray[${index}] = ${item}`);
    });