3 Stimmen

Erstelle eine schreibgeschützte/unveränderliche Kopie eines beliebigen Objekts (einschließlich tiefer Eigenschaften)

Wie kann ich in JavaScript eine schreibgeschützte/unveränderliche Version eines Objekts erstellen, dessen Eigenschaften nicht geändert werden können? Dies sollte auch für die Eigenschaften aller Untergebenen Objekte und so weiter gelten.

Alle Methoden, auf die ich gestoßen bin (Object.defineProperty, Object.freeze, usw.) funktionieren nur für die obersten Ebenen des Objekts, nicht aber für die Unterobjekte.

(Ein möglicher Anwendungsfall: Nachdem Sie ein Einstellungen oder Konfiguration Typ-Objekt in einem bestimmten Modul erstellt/geändert haben, müssen Sie es im unveränderlichen Zustand den anderen Modulen des Programms zugänglich machen.)

6voto

Himanshu P Punkte 8937

Dies ist die Lösung, die ich nach einigem Überlegen gefunden habe. Funktioniert gut für meine Bedürfnisse, deshalb dachte ich, ich würde sie im Frage-Antwort-Stil teilen. Bitte schlagen Sie Verbesserungen/Probleme vor, wenn Sie welche finden.

/**
 * Macht das angegebene Objekt (tiefgehend) unveränderbar oder "schreibgeschützt", sodass keine seiner Eigenschaften (oder Teil-Eigenschaften) geändert werden können. Das konvertierte Objekt wird zurückgegeben.
 * @param {object} obj Eingabeobjekt
 */
makeImmutable: function makeImmutable (obj) {
    if ((typeof obj === "object" && obj !== null) ||
        (Array.isArray? Array.isArray(obj): obj instanceof Array) ||
        (typeof obj === "function")) {

        Object.freeze(obj);

        for (var key in obj) {
            if (obj.hasOwnProperty(key)) {
                makeImmutable(obj[key]);
            }
        }
    }
    return obj;
}

EDIT: Der Code wurde vereinfacht. Behandelt jetzt auch Arrays korrekt.

0voto

talves Punkte 13523

Von dieser Lösung fasziniert.

Hier ist der Code-Schnipsel mit einem Beispiel:

/**
 * Macht das angegebene Objekt (tiefgreifend) unveränderlich oder "schreibgeschützt", sodass keine seiner Eigenschaften (oder Untereigenschaften) geändert werden können. Das konvertierte Objekt wird zurückgegeben.
 * @param {object} obj Eingabeobjekt
 */
makeImmutable: function makeImmutable(obj) {
  if ((typeof obj === "object" && obj !== null) ||
    (Array.isArray ? Array.isArray(obj) : obj instanceof Array) ||
    (typeof obj === "function")) {

    Object.freeze(obj);

    for (var key in obj) {
      if (obj.hasOwnProperty(key)) {
        makeImmutable(obj[key]);
      }
    }
  }
  return obj;
}

var newObj = {
  thisArrayOfObjects: [{
    propertyOne: 'value1',
    propertyTwo: 'value2'
  }]
};
newObj.thisArrayOfObjects.push({
  propertyBefore: 'before3'
});

console.log('newObj', newObj);
$('#viewer').append('newObj: ' + JSON.stringify(newObj));

makeImmutable(newObj);

console.log('imutable', newObj);
$('#viewer').append('imutable: ' + JSON.stringify(newObj));
try {
  newObj.thisArrayOfObjects.push({
    propertyThree: 'value3'
  });
} catch (e) {
  $('#viewer').append('immutable error: ' + e.message);
  console.log('immutable error:', e.message);
}

0voto

S.D. Punkte 28774

Tolle Antworten bereits. Dieser verwendet lodash:

var _ = require('lodash');

Um ein Objekt unveränderlich zu machen:

/**
 * Macht ein Objekt unveränderlich, indem alle eigenen Eigenschaften (tief) eingefroren werden.
 * @param {*} obj - Objekt, das unveränderlich gemacht werden soll.
 * @returns {*} Das Eingabeobjekt.
 */
function deepFreeze(obj) {
    if (_.isObject(obj) || _.isArray(obj) || _.isFunction(obj)) {
        Object.freeze(obj);
        _.forOwn(obj, deepFreeze);
    }
    return obj;
}

Um einen unveränderlichen Klon zu erstellen:

var frozenClone = deepFreeze(_.cloneDeep(obj));

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X