关于 ClosureOnModifiedVariable 的 ReSharper 警告 - 为什么?
ReSharper warning about ClosureOnModifiedVariable - why?
所以我在审查期间发现了这段代码:
var permissions = $("#" + me.map.permissionsGridHtmlId).data("kendoGrid").dataSource.data();
var data = form.serializeArray();
for (var i = 0; i < permissions.length; i++) {
var record = permissions[i].toJSON();
$.each(record, function (key, value) {
data.push({
// ReSharper disable once ClosureOnModifiedVariable
name: "Permissions[" + i + "]." + key,
value: value
});
});
}
“// ReSharper 禁用”评论让我停顿了一下。
我试图调查它,发现了这个 - https://www.jetbrains.com/help/resharper/AccessToForEachVariableInClosure.html
但是,我尝试删除注释,然后按照link所说的,在范围内创建一个变量来存储值,但警告并没有消失。
此外,尽管有警告,它似乎按设计运行 - 'i' 的值正确更改,最后 'data' 变量存储 proper/expected 值。
所以,我的问题是...为什么 ReSharper 会对此发出警告?代码中是否存在实际问题,或者 ReSharper 中是否存在错误?如果是前者,我应该如何修复代码?如果是后者,这个警告 ever 是正确的(所以我们应该留下禁用评论)还是我应该更改检查严重性以从不显示此警告?
更新
对代码进行以下更改使警告消失:
$.each(permissions, function (i, permission) {
$.each(permission.toJSON(), function (key, value) {
data.push({
name: "Permissions[" + i + "]." + key,
value: value
});
});
});
我仍然想知道 为什么 警告存在,但是,当两个代码片段似乎表现相同时。
只有在变量修改后执行 lambda(在您的情况下为函数参数)时,访问修改后的闭包才会成为问题。在你的情况下,$.each
应该立即执行 lambda,所以这应该不是问题。但是 ReSharper 不知道被调用的函数是会立即执行传递的 lambda 还是会存储它供以后执行,尤其是在 JavaScript 中使用动态类型。所以它总是给出警告。
请注意,您找到的文章涉及 C#,它建议的修复仅对 C# 有效。您不能使用 var i1 = i
来解决 JS 中的问题,因为 var
声明的变量 i1
将具有函数作用域,而您需要它具有块作用域。因此,如果您可以使用 ECMAScript 2015,那么您可以使用 let
或 const
来声明具有块作用域的变量,例如:
var permissions = $("#" + me.map.permissionsGridHtmlId).data("kendoGrid").dataSource.data();
var data = form.serializeArray();
for (var i = 0; i < permissions.length; i++) {
var record = permissions[i].toJSON();
let i1 = i;
$.each(record, function (key, value) {
data.push({
name: "Permissions[" + i1 + "]." + key,
value: value
});
});
}
所以我在审查期间发现了这段代码:
var permissions = $("#" + me.map.permissionsGridHtmlId).data("kendoGrid").dataSource.data();
var data = form.serializeArray();
for (var i = 0; i < permissions.length; i++) {
var record = permissions[i].toJSON();
$.each(record, function (key, value) {
data.push({
// ReSharper disable once ClosureOnModifiedVariable
name: "Permissions[" + i + "]." + key,
value: value
});
});
}
“// ReSharper 禁用”评论让我停顿了一下。 我试图调查它,发现了这个 - https://www.jetbrains.com/help/resharper/AccessToForEachVariableInClosure.html
但是,我尝试删除注释,然后按照link所说的,在范围内创建一个变量来存储值,但警告并没有消失。
此外,尽管有警告,它似乎按设计运行 - 'i' 的值正确更改,最后 'data' 变量存储 proper/expected 值。
所以,我的问题是...为什么 ReSharper 会对此发出警告?代码中是否存在实际问题,或者 ReSharper 中是否存在错误?如果是前者,我应该如何修复代码?如果是后者,这个警告 ever 是正确的(所以我们应该留下禁用评论)还是我应该更改检查严重性以从不显示此警告?
更新
对代码进行以下更改使警告消失:
$.each(permissions, function (i, permission) {
$.each(permission.toJSON(), function (key, value) {
data.push({
name: "Permissions[" + i + "]." + key,
value: value
});
});
});
我仍然想知道 为什么 警告存在,但是,当两个代码片段似乎表现相同时。
只有在变量修改后执行 lambda(在您的情况下为函数参数)时,访问修改后的闭包才会成为问题。在你的情况下,$.each
应该立即执行 lambda,所以这应该不是问题。但是 ReSharper 不知道被调用的函数是会立即执行传递的 lambda 还是会存储它供以后执行,尤其是在 JavaScript 中使用动态类型。所以它总是给出警告。
请注意,您找到的文章涉及 C#,它建议的修复仅对 C# 有效。您不能使用 var i1 = i
来解决 JS 中的问题,因为 var
声明的变量 i1
将具有函数作用域,而您需要它具有块作用域。因此,如果您可以使用 ECMAScript 2015,那么您可以使用 let
或 const
来声明具有块作用域的变量,例如:
var permissions = $("#" + me.map.permissionsGridHtmlId).data("kendoGrid").dataSource.data();
var data = form.serializeArray();
for (var i = 0; i < permissions.length; i++) {
var record = permissions[i].toJSON();
let i1 = i;
$.each(record, function (key, value) {
data.push({
name: "Permissions[" + i1 + "]." + key,
value: value
});
});
}