2016-11-05 4 views
1

下記の浅いコピーを取得して1つのレイヤーだけを深くする方法はありますか?私は完全に異なるデザインを使ってこれを修正する手段がありますが、他の誰かが私が文字列に変換しようとしているものに遭遇したのかどうか疑問に思っていました。JavaScript:循環参照オブジェクトのシャローコピーをストライミングしますか?

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

?循環構造をJSONに変換する – Mahi

+0

期待する結果の例を挙げることはできますか? –

+1

コピーするものは何もありません。浅いクローンを作成することは、コンストラクタを再呼び出しして新しいオブジェクトを作成することと同じです。私はあなたが貼り付けていない他のコードがあると仮定します。 –

答えて

2

それはあなたが求めているものを少しは不明だが、あなたの目標は、単に円形オブジェクトを文字列化する場合、あなたはあなたのオブジェクトが

を表すことがしたい方法を指定する toJSONをオーバーライドする必要があります

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))

これはおそらく、私はあなたのコードの多くを見ることなくあなたを助けることができる最善の方法です。どのようにこのコードを使用しているのかわかりませんが、どのような場合でも、これはおそらくあなたのクラスのための最高のデザインではありません。残りのクラスとそれを使用するコードを共有すると、より効果的にあなたを助けることができます。

+0

これは1つの方法ですが、toJSONに、「浅いクローン」として要求したものを呼び出すために変更できる特定のパラメータがあったのかどうか疑問に思っていましたが、この場合はネイティブにオーバーライドしています。私はこれをupvoteし、おそらくこのデザインパターンを無視し、その周りの代替方法を見てください。この記事の全理由は、循環参照はクライアントでうまくいきますが、ネットワークを介してあるクライアントから別のクライアントにデータを送信しようとすると、循環参照のためにスタックオーバーフローが発生していたからです。 – simon

0

JSON.stringifyについてMDNリファレンスをチェックすると、2番目のパラメータとしてreplacer機能を受け入れることがわかります。この関数は、文字列化したい要素を少しマッサージするのに便利です。

これは、循環的な問題を回避するのに役立ちます。

例えば:しかし

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);

、およびマニュアルに記載されているとの例を実行している示されているように:

注:削除する代用機能を使用することはできません値を配列から取得します。未定義または関数を返すと、代わりにnullが使用されます。

これらのヌルで何らかの方法で対処する必要があります。とにかく、あなたはこの機能で遊んで、それをあなたのニーズに「適応させる」ことができます。たとえば、あなたの例に適用:

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

を問題を解決し、JSON.stringifyシンプルさを保つために、私は

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; 
}; 

(ここでは私の脱水方法で)、次のアプローチを使用しますこれはTypeScriptですが、メソッド内で結果を得るために強い型を使用すると、私たちはいくらかの混乱を招くことに注意してください。

アレイ検索の代わりに残念ながら私はforを使用しなければなりませんでした。なぜなら、単純に私にはうまくいかなかったからです。