RequireJs 在合并文件时打破了我的 for 循环 (r.js)
RequireJs is breaking my for loop when combining files (r.js)
我正在使用 RequireJs 并用于生产版本 combining/minify-ing 并使用 r.js 对其进行 uglify-ing,但是 运行 出现了一个与它如何处理我的一个 FOR 相关的错误循环。
我关闭了 r.js 构建中的所有优化,所以现在它只是将代码合并到一个文件中,而不是 minifying/uglifying;但是,错误仍然存在。
原始(简体)代码:
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 (优化:"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 循环移动到一个函数中,所以我无法更改索引,所以之后removing/splicing 一个值并向后移动索引,对索引的更改将完全丢失,并跳过数组中的下一项。
解决方法
我可以将索引从前到后循环,这样我就不需要更改索引,但我正在执行其他需要按顺序(从前到后)完成的计算。另外,我担心将来这个错误会潜入我的代码中。
问题
这就是 r.js 的工作方式吗(我是不是错过了一个简单的设置)?
我是否在使用反模式编码并且应该改变我的方法?
谢谢!
更新
如评论中所述,解决方案是将 i
的声明从 for
循环结构中拉出:
var i;
for (i = 0; i < myArray.length; i++) {
// ...
}
意见:由于there is no functional difference在两种声明方式i
之间,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}`);
});
我正在使用 RequireJs 并用于生产版本 combining/minify-ing 并使用 r.js 对其进行 uglify-ing,但是 运行 出现了一个与它如何处理我的一个 FOR 相关的错误循环。
我关闭了 r.js 构建中的所有优化,所以现在它只是将代码合并到一个文件中,而不是 minifying/uglifying;但是,错误仍然存在。
原始(简体)代码:
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 (优化:"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 循环移动到一个函数中,所以我无法更改索引,所以之后removing/splicing 一个值并向后移动索引,对索引的更改将完全丢失,并跳过数组中的下一项。
解决方法
我可以将索引从前到后循环,这样我就不需要更改索引,但我正在执行其他需要按顺序(从前到后)完成的计算。另外,我担心将来这个错误会潜入我的代码中。
问题
这就是 r.js 的工作方式吗(我是不是错过了一个简单的设置)?
我是否在使用反模式编码并且应该改变我的方法?
谢谢!
更新
如评论中所述,解决方案是将 i
的声明从 for
循环结构中拉出:
var i;
for (i = 0; i < myArray.length; i++) {
// ...
}
意见:由于there is no functional difference在两种声明方式i
之间,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}`);
});