JSON.stringify()的陷阱及其隱藏的秘密
如果你接觸過(guò) JavaScript,很有可能遇到過(guò) JSON.stringify()—— 這個(gè)可靠的工具可以將對(duì)象轉(zhuǎn)換為 JSON 字符串。無(wú)論是通過(guò) API 發(fā)送數(shù)據(jù)還是保存結(jié)構(gòu)化數(shù)據(jù),對(duì)于任何 Web 開(kāi)發(fā)者來(lái)說(shuō),JSON.stringify() 實(shí)際上都是一個(gè)必經(jīng)之路。但盡管它看起來(lái)就像揮動(dòng)魔杖一樣簡(jiǎn)單,表面之下卻隱藏著陷阱。讓我們以一種有趣的方式深入探索 JSON.stringify() 這個(gè)古怪的世界,并了解一些歷史趣聞!
簡(jiǎn)史:JSON.stringify() 從何而來(lái)?
在我們探索陷阱之前,讓我們回到它的最初。JSON.stringify()是在 ECMAScript 5(ES5)中引入的,該腳本于 2009 年完成。目的是什么?以機(jī)器和人類(lèi)都可讀的方式簡(jiǎn)化數(shù)據(jù)交換。
有趣的事實(shí):JSON(JavaScript 對(duì)象表示法)本身最初是由 Douglas Crockford 在 2000 年代初期構(gòu)思的,他正在尋找一種輕量級(jí)的數(shù)據(jù)格式來(lái)取代 XML。
JSON.stringify() 的陷阱
1、循環(huán)引用:兜兜轉(zhuǎn)轉(zhuǎn)我們走!
循環(huán)引用是JSON.stringify()的最終禁忌。如果你嘗試字符串化引用自身的對(duì)象,你會(huì)得到一個(gè)很清晰的報(bào)錯(cuò):Uncaught TypeError。
const obj = {};
obj.self = obj;
JSON.stringify(obj); // Uncaught TypeError: Converting circular structure to JSON
有趣的事實(shí):您可以說(shuō)JSON.stringify()具有“無(wú)無(wú)限循環(huán)”策略!它只是不適合遞歸對(duì)象。要是逃離生活的圈子就這么容易就好了,對(duì)吧?
2、不可枚舉的屬性和符號(hào)?不受歡迎!
當(dāng)使用JSON.stringify()時(shí),任何不可枚舉或基于 Symbol 的屬性都會(huì)像魔術(shù)一樣消失得無(wú)影無(wú)蹤。
const obj = {};
Object.defineProperty(obj, 'hidden', { value: 'secret', enumerable: false });
obj[Symbol('id')] = 123;
console.log(JSON.stringify(obj)); // {}
有趣的事實(shí):不可枚舉的屬性就像 JavaScript 的忍者 — 安靜、不可見(jiàn),并且完全被JSON.stringify()忽略!
3、未定義的值是重影
undefined 值以及函數(shù)和 Symbol 將被完全忽略。它們不會(huì)在您的最終 JSON 輸出中被剪切。
const obj = {
name: 'John',
age: undefined,
greet: function() { console.log('Hello!'); },
};
console.log(JSON.stringify(obj)); // {"name":"John"}
有趣的事實(shí):想象一下,undefined的價(jià)值觀就像在聚會(huì)上被排除在客人名單之外的人。如果他們不受歡迎,他們就不會(huì)出現(xiàn)!
4、NaN 和 Infinity — Math Gone MIA
如果您的對(duì)象包含 NaN 或 Infinity,則它們?cè)谧罱K的 JSON 字符串中將替換為 null。
const obj = { value: NaN, count: Infinity };
console.log(JSON.stringify(obj)); // {"value":null,"count":null}
有趣的事實(shí):NaN是一個(gè)悖論。它被稱(chēng)為 “數(shù)字”,但不是 1!難怪 JSON.stringify()把它當(dāng)作幽靈。
5、日期變成字符串 — 不包括時(shí)間旅行
字符串化后,日期不會(huì)保留為 Date 對(duì)象。相反,它們將被轉(zhuǎn)換為 ISO 字符串。
const obj = { date: new Date() };
console.log(JSON.stringify(obj)); // {"date":"2024-09-11T12:00:00.000Z"}
有趣的事實(shí):JavaScript 的 Date 對(duì)象因其怪癖而臭名昭著。至少當(dāng)JSON.stringify()將其轉(zhuǎn)換為字符串時(shí),它是一致的!
6、屬性順序 — 不是你所期望的
意外的JSON.stringify()不保留屬性的順序。事實(shí)上,它可能會(huì)按字母順序?qū)λ鼈冞M(jìn)行排序。
const obj = { b: 1, a: 2 };
console.log(JSON.stringify(obj)); // {"a":2,"b":1}
有趣的事實(shí):您可能會(huì)說(shuō)JSON.stringify()有點(diǎn)強(qiáng)迫癥。它喜歡按字母順序排序,無(wú)論您喜歡與否!
原型消失 — 只剩下最基本的骨架
方法和原型屬性?逝。當(dāng)JSON.stringify()執(zhí)行其操作時(shí),它只留下對(duì)象的直接屬性。
function Person(name) {
this.name = name;
}
Person.prototype.greet = function() {
console.log(`Hello, ${this.name}!`);
};
const john = new Person('John');
console.log(JSON.stringify(john)); // {"name":"John"}
有趣的事實(shí):原型就像電影中的幕后工作人員 — 必不可少,但觀眾從未見(jiàn)過(guò)(或者在這種情況下,JSON.stringify())。
JSON.stringify()參數(shù)的強(qiáng)大功能
雖然陷阱很多,但不要忘記JSON.stringify()通過(guò)其參數(shù)提供的強(qiáng)大自定義選項(xiàng)!
1、替代品:Filter Master
replacer參數(shù)允許您自定義字符串化的內(nèi)容。它可以是篩選或轉(zhuǎn)換值的函數(shù),也可以是將某些屬性列入白名單的數(shù)組。
replacer作為函數(shù):
const user = { name: 'John', age: 30 };
const jsonString = JSON.stringify(user, (key, value) => {
return key === 'age' ? undefined : value;
});
console.log(jsonString); // {"name":"John"}
replacer數(shù)組中:
const user = { name: 'John', age: 30, city: 'New York' };
const jsonString = JSON.stringify(user, ['name', 'city']);
console.log(jsonString); // {"name":"John","city":"New York"}
有趣的事實(shí):replacer的爭(zhēng)論就像俱樂(lè)部的保鏢,決定誰(shuí)可以進(jìn)入,誰(shuí)在門(mén)口被拒之門(mén)外。
2、space:JSON,但很漂亮
space參數(shù)允許您添加縮進(jìn)以提高可讀性。無(wú)論您喜歡2個(gè)空格還是制表符,這個(gè)參數(shù)都是您的好朋友。
const obj = { name: 'John', age: 30 };
console.log(JSON.stringify(obj, null, 2));
/*
{
"name": "John",
"age": 30
}
*/
console.log(JSON.stringify(obj, null, "*****"));
/*
{
*****"name": "John",
*****"age": 30
}
*/
有趣的事實(shí):space爭(zhēng)論就像你的室內(nèi)設(shè)計(jì)師。它使您的 JSON 輸出看起來(lái)美觀,因?yàn)檎l(shuí)不喜歡一些好的格式呢?
結(jié)論
要接受JSON.stringify()的怪異之處。
JSON.stringify()乍一看可能很簡(jiǎn)單,但它充滿了怪癖、邊緣情況和隱藏的力量。通過(guò)了解它的局限性并利用它的論點(diǎn),您可以避免常見(jiàn)的陷阱并像專(zhuān)業(yè)人士一樣使用它。
請(qǐng)記住,這不僅僅是將對(duì)象轉(zhuǎn)換為字符串,而是了解數(shù)據(jù)的表示方式。因此,下次您使用JSON.stringify()時(shí),您將準(zhǔn)備好避開(kāi)它隱藏的陷阱并充分利用它的靈活性!