2016-11-05 3 views
1

Gibt es eine Möglichkeit, nur eine flache Kopie von unten zu bekommen, um nur eine Schicht tief zu bekommen? Ich habe ein Mittel, um dies mit einem komplett anderen Design zu beheben, aber ich habe mich gefragt, ob jemand anderes in das, was ich versuche, in eine Zeichenkette konvertiert werden soll.JavaScript: Eine flache Kopie eines kreisförmigen Objekts referenzieren?

var SomeObjClass = function() { 
    var self = this; 
    this.group = { 
     members: [self] 
    }; 
}; 
var p = new SomeObjClass(); 
var str = JSON.stringify(p); 
+0

Fehler? Umwandeln der kreisförmigen Struktur in JSON – Mahi

+0

Können Sie ein Beispiel für Ihr erwartetes Ergebnis angeben? –

+1

Es gibt nichts zu kopieren. Ein seichter Klon wäre genauso, als würde man den Konstruktor nur neu aufrufen, um ein neues Objekt zu erstellen. Ich nehme an, es gibt anderen Code, den Sie nicht eingefügt haben. –

Antwort

2

ist es ein wenig unklar, was Sie fragen, aber wenn Ihr Ziel ist ein kreisförmiges Objekt stringify einfach ist, werden Sie toJSON außer Kraft setzen müssen, um zu bestimmen, wie Sie Ihr Objekt dargestellt werden mögen

function SomeObjClass() { 
 
    var self = this; 
 
    this.group = { 
 
    members: [self] 
 
    }; 
 
} 
 

 
SomeObjClass.prototype.addMember = function(m) { 
 
    this.group.members.push(m); 
 
}; 
 

 
// when stringifying this object, don't include `self` in group.members 
 
SomeObjClass.prototype.toJSON = function() { 
 
    var self = this; 
 
    return { 
 
    group: { 
 
     members: self.group.members.filter(function (x) { 
 
     return x !== self 
 
     }) 
 
    } 
 
    }; 
 
} 
 

 
var a = new SomeObjClass(); 
 
var b = new SomeObjClass(); 
 
a.addMember(b); 
 

 
console.log(JSON.stringify(a))

Dies ist wahrscheinlich das beste, was ich Ihnen ohne zu sehen, mehr von Ihrem Code helfen kann. Ich weiß nicht, wie Sie diesen Code verwenden, aber was auch immer der Fall ist, das ist wahrscheinlich nicht das beste Design für Ihre Klasse. Wenn Sie den Rest der Klasse und den Code teilen, der sie verwendet, können wir Ihnen wahrscheinlich effektiver helfen.

+0

Dies ist eine Methode, aber ich frage mich, ob toJSON bestimmte Parameter hatte, die ich im Aufruf modifizieren könnte, um das zu tun, was ich als 'seichten Klon' angefordert habe, aber in diesem Fall überschreiben Sie, was es nativ tut. Ich werde dies auffrischen und wahrscheinlich dieses Designmuster ignorieren und nach alternativen Wegen suchen. Der ganze Grund für diesen Post ist, weil zirkuläre Referenzen in einem Client in Ordnung sind, wenn versucht wird, Dinge wie das Senden der Daten von einem Client zu einem anderen über ein Netzwerk zu tun, kam es aufgrund des zirkulären Verweises zu einem Stapelüberlauf. – simon

0

Wenn Sie MDN-Referenz über JSON.stringify überprüfen, sehen Sie, dass es als zweiter Parameter eine replacer-Funktion akzeptiert. Diese Funktion ist nützlich, um ein bisschen die Elemente zu massieren, die Sie stringieren möchten.

Es könnte Ihnen helfen, Ihr zirkuläres Problem zu vermeiden.

Zum Beispiel:

function avoidCircularReference(obj) { 
 
    return function(key, value) { 
 
    return key && typeof value === 'object' && obj === value ? undefined : value; 
 
    }; 
 
} 
 

 
var SomeObjClass = function() { 
 
    var self = this; 
 
    this.group = { 
 
     members: [self, {a:'f', b: [self]}] 
 
    }; 
 
}; 
 
var p = new SomeObjClass(); 
 
var str = JSON.stringify(p, avoidCircularReference(p)); 
 
console.log(str);

jedoch, wie in der Dokumentation angegeben und gezeigt das Beispiel ausgeführt wird:

Hinweis: Sie können nicht die replacer Funktion nutzen zu entfernen Werte aus einem Array. Wenn Sie undefined oder eine Funktion zurückgeben, wird stattdessen null verwendet.

Also müssten Sie in irgendeiner Weise mit diesen Nullen umgehen. Wie auch immer, Sie könnten mit dieser Funktion spielen und sie an Ihre Bedürfnisse anpassen. Zum Beispiel und auf Ihr Beispiel:

function avoidCircularReference(obj) { 
 
    var removeMeFromArray = function(arr) { 
 
    var index = arr.indexOf(obj); 
 
    if (index > -1) { 
 
     arr.splice(index, 1); 
 
    } 
 
    }; 
 

 
    return function(key, value) { 
 
    if (Object.prototype.toString.call(value) === "[object Array]") { 
 
     removeMeFromArray(value); 
 
    } 
 
    return value; 
 
    }; 
 
} 
 

 
var SomeObjClass = function() { 
 
    var self = this; 
 
    this.group = { 
 
    members: [self, { 
 
     a: 'f', 
 
     b: [self] 
 
    }] 
 
    }; 
 
}; 
 
var p = new SomeObjClass(); 
 
var str = JSON.stringify(p, avoidCircularReference(p)); 
 
console.log(str);

0

Um das Problem zu lösen, und halten Sie die JSON.stringify Einfachheit, verwende ich den folgenden Ansatz (hier in meiner dehydrate Methode)

public dehydrate(): string { 
    var seenObjects = []; 
    function inspectElement(key, value) { 
     if (detectCycle(value)) { 
      return '[Ciclical]'; 
     } else { 
      return value; 
     }; 
    }; 
    function detectCycle(obj): boolean { 
     if (obj && (typeof obj == 'object')) { 
      for (let r of seenObjects) { 
       if (r == obj) { 
        return true; 
       }; 
      }; 
      seenObjects.push(obj); 
     }; 
     return false; 
    }; 
    let json: string = JSON.stringify(this, inspectElement,' '); 
    return json; 
}; 

Beachten Sie, dass TypeScript zwar die Verwendung starker Typen zum Erreichen der Ergebnisse innerhalb der Methode zu einiger Verwirrung führt.

Leider musste ich for statt Array-Suche verwenden, weil es einfach nicht zu mir funktioniert hat.

Verwandte Themen