在for循环中处理let和const时,我遇到了一些奇怪的结果。我的印象是,使用let或const定义的变量的范围仅限于它周围的括号。
因此在for循环中,将为每个let和const定义一个新的作用域。但是,for循环中的一些变量是每次迭代都带有范围。奇怪的是,它不是for循环中的所有变量。
如果是所有这些我会猜测我关于let和const范围如何工作的假设是错误的。只有他们中的一些人携带这一事实对我来说并不合理。
我在Chrome中运行此版本 - 版本60.0.3112.113(官方版本)(64位)
我已经删除了一些代码,以使其更简洁,但请查看"// ***"
以查看我的变量范围无意义。
for (let i = 0; i < combinedRoles.length; i++)
{
// *** orgs, permObjArray, roleOrgTree, rolePanelId are all carrying scope
const orgs = $sidebar.data("org-tree");
const orgRole = combinedRoles[i];
const roleId = orgRole.roleId;
const permObjArray = orgRole.permObjsArray;
const rolePanelId = "#user-" + user.userId + "-role-" + roleId;
const $selectedRoleRow = $userPanel.find(".role-selection-row.selected");
let $roleSelection = $userPanel.find(rolePanelId);
$roleSelection.data("roleData", orgRole);
// *** roleOrgTree's scope is carrying over between "i" iterations
// *** So below when I set the data value for the html element from before.
let roleOrgTree = [];
roleOrgTree = orgs.map(function(org)
{
let stateObj = {checked : false, checkbox_disabled : false, selected : false};
org.a_attr = { "class" : "role-org-tree-anchor" };
org.li_attr = { "class" : "role-org-tree-li" }
currUserOrgPerms = org.anmUserRole.permissions;
if ($.inArray(roleId, org.availableRoleIds) < 0)
{
org.a_attr = { "class" : "role-org-tree-anchor disable-org-tree-anchor role-not-available" };
org.li_attr = { "class" : "role-org-tree-li disable-org-tree-node" }
stateObj.checkbox_disabled = true;
}
org.state = stateObj;
return org;
});
// *** What's happening is since roleOrgTree's scope is carrying over
// *** it is changing the previous element's data object
$roleSelection.data("roleOrgTree", roleOrgTree);
// *** However the scope is not carrying over for permissionsTree
// *** and each html element's data object is correct
let permissionsTree = [];
let familyTree = [];
// Creating the permissions tree for this role
//permObjArray.forEach(function(obj) {
permissionsTree = permObjArray.map(function(obj) {
const permFamily = obj.perm_family;
if (familyTree.indexOf(permFamily) < 0)
{
familyTree.push(permFamily);
const familyObj = {
id: permFamily,
text : permFamily,
parent : "#",
li_attr: { "class" : "disable-org-tree-node" },
a_attr : { "class" : "disable-org-tree-anchor hide-checkbox" }
};
permissionsTree.push(familyObj);
}
obj.state = {checked: true, selected: true, checkbox_disabled : true};
obj.li_attr = { "class" : "disable-org-tree-node" };
obj.a_attr = { "class" : "disable-org-tree-anchor" };
return obj;
});
// *** permissionsTree scope is not carrying over so the previous
// *** element's ($roleSelection) data object is not getting over written
$roleSelection.data("rolePermTree", permissionsTree);
};
从我的chrome开发人员工具中,您可以看到右侧的&#34; Scope&#34;并阻止变量已经有一个范围,但只是未定义。为什么会这样?
答案 0 :(得分:1)
$sidebar.data("org-tree")
没有复制数据,它只是返回对它的引用。因此,当您稍后映射orgs
并执行:
org.a_attr = ...;
org.li_attr = ...;
您正在修改元素数据中的对象,这会影响循环的下一次迭代。
您应该在修改这些对象之前克隆它们。
roleOrgTree = orgs.map(function(org)
{
org = Object.assign({}, org);
let stateObj = {checked : false, checkbox_disabled : false, selected : false};
org.a_attr = { "class" : "role-org-tree-anchor" };
org.li_attr = { "class" : "role-org-tree-li" }
currUserOrgPerms = org.anmUserRole.permissions;
if ($.inArray(roleId, org.availableRoleIds) < 0)
{
org.a_attr = { "class" : "role-org-tree-anchor disable-org-tree-anchor role-not-available" };
org.li_attr = { "class" : "role-org-tree-li disable-org-tree-node" }
stateObj.checkbox_disabled = true;
}
org.state = stateObj;
return org;
});
顺便说一下,如果您立即从roleOrgTree = []
重新分配orgs.map()
,那么初始化_
毫无意义。