组合文件时,RequireJs会破坏我的for循环(r.js)

时间:2018-02-08 18:51:45

标签: javascript requirejs

我正在使用RequireJs和生产版本使用r.js组合/缩小和uglify-ing,但是遇到了与它如何处理我的一个FOR循环相关的错误。

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

原始(简化)代码:

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循环移动到一个函数中,所以在删除/拼接一个值并移动之后我无法改变索引返回索引,对索引的更改将完全丢失,并跳过数组中的下一个项目。

解决方法

我可以将索引循环回到前面,所以我不需要改变索引,但是我正在执行其他需要按顺序完成的计算(从前到后)。另外,我担心这个漏洞会在未来隐藏在我的代码中。

问题

这是r.js应该如何工作(我错过了一个简单的设置)?

我是否采用反模式进行编码并且应该改变我的方法?

谢谢!

1 个答案:

答案 0 :(得分:0)

<强>更新

正如评论中所讨论的,解决方案是将i的声明从for循环结构中拉出来:

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

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

当然,您也可以选择Array.prototype.filter完全避开问题:

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

使用Array.prototype.forEach

也可以在过滤之前和之后执行其他逻辑

&#13;
&#13;
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}`);
});
&#13;
&#13;
&#13;