ES6 Let Const Block Scope переносится внутрь для цикла для некоторых переменных

1

Я испытываю некоторые причудливые результаты при работе с let и const внутри цикла for. Я был под впечатлениями, что переменная, определенная с let или const, имеет область действия, ограниченную окружающими ее скобками.

Таким образом, в цикле for для каждого let и const будет определена новая область. Однако некоторые из моих переменных внутри цикла for несут область видимости с каждой итерации. Что странно, так это не все переменные внутри цикла for.

Если бы все они были, я бы догадался, что мое предположение о том, как работает функция let и const, было неправильным. Тот факт, что только некоторые из них несут, не имеет для меня смысла.

Я запускаю это в Chrome - Version 60.0.3112.113 (Official Build) (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 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 happening is since roleOrgTree scope is carrying over 
        // *** it is changing the previous element data object
        $roleSelection.data("roleOrgTree", roleOrgTree);

        // *** However the scope is not carrying over for permissionsTree 
        // *** and each html element 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 ($roleSelection) data object is not getting over written
        $roleSelection.data("rolePermTree", permissionsTree);
    };

Из моих инструментов разработчика Chrome вы можете видеть, что с правой стороны в разделе "Область" и "Блокировать переменные" уже есть область действия, но они просто не определены. Почему это так?

Изображение 174551

  • 0
    Трудно понять проблему так, как вы ее описали. Можете ли вы добавить HTML и объяснить, что он должен делать и что он делает вместо этого?
  • 0
    Вы $sidebar.data("org-tree") объекты org , которые сохраняются в $sidebar.data("org-tree") .
Показать ещё 4 комментария
Теги:
ecmascript-6
scope

1 ответ

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().

  • 0
    инициализация roleOrgTree была отчаянной, я не мог понять, что вызвало сферу действия, и пытался что-нибудь предпринять.
  • 0
    Это сработало, и я изначально только что сделал новый экземпляр roleOrgTree сразу после сопоставления, и это тоже сработало, но я не мог понять, почему будет реализована область действия. Событие все еще с этим, когда я приостанавливаю отладчик в первой строке цикла for, roleOrgTree все еще определяется на следующей итерации. Я все еще что-то упускаю?
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню