ES6让Const块范围在一些变量的内部进行循环

时间:2017-09-19 16:32:19

标签: javascript scope ecmascript-6

在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;并阻止变量已经有一个范围,但只是未定义。为什么会这样?

Screenshot

1 个答案:

答案 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(),那么初始化_毫无意义。