2016-11-05 59 views
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

這是一種解決方法,但我想知道是否在調用JSON時可以修改特定參數以執行我所要求的「淺層克隆」,但在這種情況下,您將覆蓋原有內容。我會贊成這一點,可能會忽略這種設計模式,並考慮其他方式。這篇文章的全部原因是因爲雖然循環引用在客戶端很好,但是當嘗試執行諸如通過網絡將數據從一個客戶端發送到另一個客戶端時,由於循環引用的緣故,堆棧溢出是隨之而來的。 – simon

0

如果您檢查關於JSON.stringify的MDN參考,您會看到它接受作爲第二個參數的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而不是數組搜索,因爲它根本不適用於我。