ключ объекта удален, но все еще повторяется в цикле - PullRequest
0 голосов
/ 25 марта 2020

Учитывая EcmaScript Section 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 заявляет, что он удалит из текущей итерации! Что не так и как я могу это исправить?

1 Ответ

0 голосов
/ 25 марта 2020

Вы не делаете перечисление. Вы создаете массив, а затем удаляете свойства во время итерации 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 массив. То же самое происходит в вашем reduce звонке. Вы могли бы избежать этого, используя реальный for … in l oop.


Однако, реальная ошибка в вашем коде -

mapping = false;
this.MAPPINGS.forEach((mapping) => {
//                      ^^^^^^^
    if (mapping[0].test(key)){
        mapping[1](copy, key, acc, i);
        mapping = true;
//      ^^^^^^^
    }
});

, где вы не устанавливаете внешний -scope логическая переменная mapping, равная true, которая предотвращает копирование значения в результат, но вместо этого вы просто перезаписываете параметр mapping вашего обратного вызова forEach.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...