118 votes

Copie en profondeur dans ES6 en utilisant la syntaxe "spread".

J'essaie de créer une méthode de carte de copie profonde pour mon projet Redux qui fonctionnera avec des objets plutôt que des tableaux. J'ai lu que dans Redux, chaque état ne doit rien changer aux états précédents.

export const mapCopy = (object, callback) => {
    return Object.keys(object).reduce(function (output, key) {

    output[key] = callback.call(this, {...object[key]});

    return output;
    }, {});
}

Ça marche :

    return mapCopy(state, e => {

            if (e.id === action.id) {
                 e.title = 'new item';
            }

            return e;
        })

Cependant, il ne copie pas en profondeur les éléments internes et je dois donc le modifier :

export const mapCopy = (object, callback) => {
    return Object.keys(object).reduce(function (output, key) {

    let newObject = {...object[key]};
    newObject.style = {...newObject.style};
    newObject.data = {...newObject.data};

    output[key] = callback.call(this, newObject);

    return output;
    }, {});
}

C'est moins élégant car il faut savoir quels objets sont passés. Existe-t-il un moyen dans ES6 d'utiliser la syntaxe étendue pour copier profondément un objet ?

0 votes

9 votes

C'est un problème XY. Vous ne devriez pas avoir à travailler beaucoup sur les propriétés profondes dans redux. Au lieu de cela, vous devriez juste créer un autre reducer qui travaille sur la tranche enfant de la forme d'état et ensuite utiliser combineReducers pour composer les deux (ou plus) ensemble. Si vous utilisez des techniques de redux idiomatiques, votre problème de clonage profond des objets disparaît.

0 votes

"Existe-t-il un moyen dans ES6 d'utiliser la syntaxe spread pour copier en profondeur un objet ?". Dans le cas général, impossible. L'appel de la syntaxe d'étalement au niveau supérieur quel qu'il soit écrase les propriétés avec profondeur qui auraient dû être fusionnées.

1voto

Jeroen Breen Points 50
function deepclone(obj) {
    let newObj = {};

    if (typeof obj === 'object') {
        for (let key in obj) {
            let property = obj[key],
                type = typeof property;
            switch (type) {
                case 'object':
                    if( Object.prototype.toString.call( property ) === '[object Array]' ) {
                        newObj[key] = [];
                        for (let item of property) {
                            newObj[key].push(this.deepclone(item))
                        }
                    } else {
                        newObj[key] = deepclone(property);
                    }
                    break;
                default:
                    newObj[key] = property;
                    break;

            }
        }
        return newObj
    } else {
        return obj;
    }
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X