对象键已删除,但仍在循环中迭代

问题描述 投票:0回答:1

给出EcmaScript第12.6.4节:

正在枚举的对象的属性可能会在列举。如果在访问期间尚未访问过的物业枚举被删除,将不会被访问。

但是,请检查此情况:

class Lead {
    MAPPINGS = [
        [
            /Medication_Types_(\d+)/,
            (data, key, acc, i) => {
                const values = Object.keys(data)
                                     .filter( key => /Medication_Types_(\d+)/.test(key ))
                                     .map(key => data[key]);

                console.log('the values: ', values);
                acc['Medication_Types'] = values;

                Object.keys(data).forEach( key => {
                    if( /Medication_Types_(\d+)/.test(key)) delete data[key];
                })

                return i;
            }
        ]
    ]

    format(data) {
        const copy = JSON.parse(JSON.stringify(data));
        let mapping = false;
        let i = 1;

        const result = Object.keys(copy).reduce((acc, key) => {
            mapping = false;
            this.MAPPINGS.forEach( (mapping) => {
                if(mapping[0].test(key)){
                    mapping[1](copy, key, acc, i);
                    mapping = true;
                }
            });

            if(!mapping){
                acc[key] = copy[key];
            }

            return acc;
        }, {});

        return result;
    }
}

const data = {
    "Gender" : "Male",
    "Medication_Types_1" : "A",
    "Medication_Types_2" : "B",
    "First_Name" : "bob"
}

const lead = new Lead();
const result = lead.format(data);
console.log('the result: ', result);

它输出:

the values:  [ 'A', 'B' ]
the values:  []
the result:  {
  Gender: 'Male',
  Medication_Types: [],
  Medication_Types_1: undefined,
  Medication_Types_2: undefined,
  First_Name: 'bob'
}

如果键被真正删除,那么“值”将不会第二次打印,而是我将得到(以及我想要的):

{
      Gender: 'Male',
      Medication_Types: ['A', 'B'],
      First_Name: 'bob'
}

因此delete似乎正在删除键,但不是从当前迭代中删除键,但是EcmaScript指出它将从当前迭代中删除!有什么问题,我该如何解决?

javascript node.js ecmascript-6
1个回答
0
投票

您未进行枚举。您正在创建一个数组,然后在该数组的forEach迭代期间删除属性:

const keys = Object.keys(data);
console.log(keys); // at this point, all the keys are already in the array
keys.forEach( key => {
    if( /Medication_Types_(\d+)/.test(key)) delete data[key];
})

当您从对象中delete该属性时,不会将该属性从keys数组中删除。

© www.soinside.com 2019 - 2024. All rights reserved.