http://thecodebarbarian.com/t...
JSON.stringfy()
是將一個 JavaScript 對象轉化爲 JSON 格式字符串的標準方式。許多 JavaScript 框架在其內部,都會使用 JSON.stringify()
:Express的 res.json()
、Axios的 post
,以及webpack stats,它們都調用了 JSON.stringify()
方法,幷包含錯誤案例。javascript
譯者注:這篇文章已經被翻譯過屢次了,可是我以爲寫的太好了,因此就再翻譯一次吧,看成是加深印象。html
全部的現代 JavaScript 運行時都支持 JSON.stringify()
,甚至 IE8 都支持它。下面是一個將簡單對象轉化爲 JSON
的例子:java
const obj = { answer: 42 }; const str = JSON.stringify(obj); str; // '{"answer":42}' typeof str; // 'string'
你可能常常看到 JSON.stringify()
和 JSON.parse()
一塊兒配合使用的場景,就像下面的代碼同樣,這種模式是實現深拷貝的方式之一:webpack
const obj = { answer: 42 }; const clone = JSON.parse(JSON.stringify(obj)); clone.answer; // 42 clone === obj; // false
JSON.stringify()
在轉化對象存在循環引用時,會拋出錯誤。更簡單地說,就是若是一個對象有一個屬性指向它自己,JSON.stringify()
會拋出錯誤,好比:ios
const obj = {}; // 存在循環引用的對象,它指向它自己 obj.prop = obj; // 會拋出 "TypeError: TypeError: Converting circular structure to JSON" 異常 JSON.stringify(obj);
這是 JSON.stringify()
會拋出異常的惟一狀況,除非你經過聲明自定義的 toJSON()
方法或者 replacer
函數。儘管如此,你仍然應該將 JSON.stringify()
包含在 try/catch
語句中,由於循環引用在實踐中十分常見。git
同時,一些邊界用例下,JSON.stringify()
並不會拋出錯誤,可是你可能卻指望它拋出錯誤。好比說,JSON.stringify()
會將 NaN
和 Infinity
轉化爲 null
:github
const obj = { nan: parseInt('not a number'), inf: Number.POSITIVE_INFINITY }; JSON.stringify(obj); // '{"nan":null,"inf":null}'
JSON.stringify()
也會直接省略那些值爲 functions
和 undefined
的屬性,以下:web
const obj = { fn: function() {}, undef: undefined }; // 它會返回空對象 JSON.stringify(obj); // '{}'
JSON.stringify()
的第一個參數是被序列化爲 JSON
的對象。JSON.stringify()
實際上能夠接受 3 個參數,同時第三個參數被稱做 spaces
。spaces
參數被用於採用一種能夠提升可讀性的方式來格式化 JSON
字符串。express
你能夠傳遞類型爲 string
或者 number
的 spaces
參數。若是 spaces
爲 undefined
,那麼 JSON.stringify()
會將每一個鍵值放到單獨的一行,同時爲其增長正確的縮進空格,好比:npm
const obj = { a: 1, b: 2, c: 3, d: { e: 4 } }; // '{"a":1,"b":2,"c":3,"d":{"e":4}}' JSON.stringify(obj); // { // "a": 1, // "b": 2, // "c": 3, // "d": { // "e": 4 // } // } JSON.stringify(obj, null, ' '); // 數字 2 會達到和上面同樣的效果,它表明空格的個數 JSON.stringify(obj, null, 2);
spaces
字符串不必定非要是空格,雖然一般咱們會使用空格,好比它也能夠是下劃線:
// { // __"a": 1, // __"b": 2, // __"c": 3, // __"d": { // ____"e": 4 // __} // } JSON.stringify(obj, null, '__');
JSON.stringify()
的第二個參數是 replacer
函數。在上文的例子中,它等於 null
。JavaScript 會對對象中的每個鍵值對調用 replacer
函數,而後會使用其返回值,做爲格式化後的值,好比:
const obj = { a: 1, b: 2, c: 3, d: { e: 4 } }; // 使每一個屬性的值遞增 1 // '{"a":2,"b":3,"c":4,"d":{"e":5}}' JSON.stringify(obj, function replacer(key, value) { if (typeof value === 'number') { return value + 1; } return value; });
replacer
函數在省略敏感數據時,十分有用。假設你想要省略全部包含 password
的屬性:
const obj = { name: 'Jean-Luc Picard', password: 'stargazer', nested: { hashedPassword: 'c3RhcmdhemVy' } }; // '{"name":"Jean-Luc Picard","nested":{}}' JSON.stringify(obj, function replacer(key, value) { // 這個函數會被調用 5 次,這裏的 key 依次爲: // '', 'name', 'password', 'nested', 'hashedPassword' if (key.match(/password/i)) { return undefined; } return value; });
toJSON
方法JSON.stringify()
方法在遍歷對象的同時,也會關注那些擁有 toJSON()
方法的屬性。若是它發現 toJSON()
方法,JSON.stringify()
會調用它,而後將它的返回值替換格式化後的值,好比:
const obj = { name: 'Jean-Luc Picard', nested: { test: 'not in output', toJSON: () => 'test' } }; // '{"name":"Jean-Luc Picard","nested":"test"}' JSON.stringify(obj);
toJSON()
方法能夠返回任意的值,包括對象、基礎類型,或者 undefined
。若是 toJSON()
返回 undefined
,JSON.stringify()
將會忽略這個屬性。
不少 JavaScript 模塊使用 toJSON()
來確保序列化複雜對象的正確性,好比 Mongoose documents
和 Moment
對象。
JSON.stringify()
是 JavaScript 中較核心的基礎方法。許多庫和框架在其內部都使用它,所以,深刻的理解它,能夠幫助你更好地使用你喜歡的 npm
模塊。好比,你能夠在 Express REST API 中利用 toJSON
方法來格式化原生 Date
類型,或者在 Axios 中,可以正確地經過 HTTP 請求發送包含循環引用的對象。
關注公衆號 全棧101,只談技術,不談人生