自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

你不知道的 JSON.stringify?。?!

開(kāi)發(fā) 前端
JSON.stringify是我們經(jīng)常用到的的一個(gè)方法,它主要作用是將 JavaScript 值和對(duì)象轉(zhuǎn)換為字符串。

[[441493]]

JSON.stringify是我們經(jīng)常用到的的一個(gè)方法,它主要作用是將 JavaScript 值和對(duì)象轉(zhuǎn)換為字符串。如:

  1. JSON.stringify({ foo: "bar" }); 
  2. // => '{"foo":"bar"}' 
  3.  
  4. JSON.stringify(123); 
  5. // => '123' 

但是JS 的許多地方都有問(wèn)題,這個(gè)函數(shù)也不例外。我們可能會(huì)想象一個(gè)叫做 "stringify "的函數(shù)總是返回一個(gè)字符串......但它并沒(méi)有!

例如,如果你嘗試 stringify undefined,它返回 undefined ,而不是一個(gè)字符串。

  1. JSON.stringify(undefined); 
  2. // => undefined 

接下來(lái),我將分兩部分講:

  • 列舉 JSON.stringify 不返回字符串的情況
  • 我們將如何避免這些陷阱

什么時(shí)候 JSON.stringify 不返回字符串?

undefined、任意的函數(shù)以及 symbol 值,在序列化過(guò)程中會(huì)被忽略(出現(xiàn)在非數(shù)組對(duì)象的屬性值中時(shí))或者被轉(zhuǎn)換成 null(出現(xiàn)在數(shù)組中時(shí))。函數(shù)、undefined 被單獨(dú)轉(zhuǎn)換時(shí),會(huì)返回 undefined。

對(duì)包含循環(huán)引用的對(duì)象(對(duì)象之間相互引用,形成無(wú)限循環(huán))執(zhí)行此方法,會(huì)拋出錯(cuò)誤

我認(rèn)為 JSON.stringify 能夠返回字符串以外的東西是挺驚訝的。但在6種情況下,它可以返回undefined:

試圖在頂層對(duì) undefined 進(jìn)行序列化,會(huì)返回 undefined。

  1. JSON.stringify(undefined); 
  2. // => undefined 

嘗試序列化函數(shù)也會(huì)返回 undefined。對(duì)于常規(guī)函數(shù)、箭頭函數(shù)、異步函數(shù)和生成器函數(shù)都是如此。

  1. JSON.stringify(function foo() {}); 
  2. // => undefined 
  3.  
  4. JSON.stringify(() => {}); 
  5. // => undefined 
  6.  
  7. function bar() {} 
  8. bar.someProperty = 123; 
  9. JSON.stringify(bar); 
  10. // => undefined 

嘗試序列化symbol 也會(huì)返回 undefined。

  1. JSON.stringify(Symbol("computers were a mistake")); 
  2. // => undefined 

在瀏覽器中,試圖序列化被廢棄的document.all 也會(huì)返回 undefined。

  1. // => undefined 

這只影響到瀏覽器,因?yàn)閐ocument.all在其他環(huán)境中是不可用的,比如Node。

帶有 toJSON 函數(shù)的對(duì)象將被運(yùn)行,而不是試圖正常地序列化它們。但是如果 toJSON 返回上面的一個(gè)值,試圖在頂層序列化它將導(dǎo)致 JSON.stringify 返回undefined。

  1. JSON.stringify({ toJSON: () => undefined }); 
  2. // => undefined 
  3.  
  4. JSON.stringify({ ignored: true, toJSON: () => undefined }); 
  5. // => undefined 
  6.  
  7. JSON.stringify({ toJSON: () => Symbol("heya") }); 
  8. // => undefined 

你可以傳遞第二個(gè)參數(shù),稱為 "replacer",它可以改變序列化的邏輯。如果這個(gè)函數(shù)為頂層返回上述值之一,JSON.stringify 將返回undefined。

  1. JSON.stringify({ ignored: true }, () => undefined); 
  2. // => undefined 
  3.  
  4. JSON.stringify(["ignored"], () => Symbol("hello")); 
  5. // => undefined 

需要注意的是,其中的許多東西實(shí)際上只影響到頂層的序列化。例如,JSON.stringify({foo: undefined}),返回字符串"{}",這并不令人驚訝。

我還想提一下,TypeScript的類型定義在這里是不正確的。例如,下面的代碼類型的校驗(yàn)可以通過(guò):

  1. const result: string = JSON.stringify(undefined); 

在第2部分中,我們將討論如何更新 TypeScript 的定義以確保其正確性。

JSON.stringify 也可能遇到問(wèn)題,導(dǎo)致它拋出一個(gè)錯(cuò)誤。在正常情況下,有四種情況會(huì)發(fā)生:

循環(huán)引用會(huì)導(dǎo)致拋出一個(gè)類型錯(cuò)誤。

  1. const b = { a }; 
  2. a.b = b; 
  3.  
  4. JSON.stringify(a); 
  5. // => TypeError: cyclic object value 

注意,這些錯(cuò)誤消息在不同瀏覽器可能提示是不樣的,例如,F(xiàn)irefox 的錯(cuò)誤信息與Chrome的不同。

BigInts不能用JSON.stringify 進(jìn)行序列化,這些也會(huì)導(dǎo)致一個(gè)TypeError。

  1. JSON.stringify(12345678987654321n); 
  2. // => TypeError: BigInt value can't be serialized in JSON 
  3.  
  4. JSON.stringify({ foo: 456n }); 
  5. // => TypeError: BigInt value can't be serialized in JSON 

帶有 toJSON 函數(shù)的對(duì)象將被運(yùn)行。如果這些函數(shù)拋出錯(cuò)誤,它將冒泡到調(diào)用者。

  1. const obj = { 
  2.   foo: "ignored"
  3.   toJSON() { 
  4.     throw new Error("Oh no!"); 
  5.   }, 
  6. }; 
  7.  
  8. JSON.stringify(obj); 
  9. // => Error: Oh no

你可以傳遞第二個(gè)參數(shù),稱為 replacer。如果這個(gè)函數(shù)拋出一個(gè)錯(cuò)誤,它將冒泡。

  1. JSON.stringify({}, () => { 
  2.   throw new Error("Uh oh!"); 
  3. }); 
  4. // => Error: Uh oh! 

現(xiàn)在我們已經(jīng)看到了 JSON.stringify 不返回字符串的情況,接下來(lái),我們來(lái)看看如何避免這些問(wèn)題。

如何避免這些問(wèn)題

沒(méi)有關(guān)于如何解決這些缺陷的通用方法,所以這里只介紹一些常見(jiàn)的情況。

處理循環(huán)引用

根據(jù)個(gè)人經(jīng)驗(yàn),JSON.stringify 在傳遞循環(huán)引用時(shí)最容易出錯(cuò)。如果這對(duì)你來(lái)說(shuō)是一個(gè)常見(jiàn)的問(wèn)題,我推薦 json-stringify-safe 包,它能很好地處理這種情況。

  1. const stringifySafe = require("json-stringify-safe"); 
  2.  
  3. const a = {}; 
  4. const b = { a }; 
  5. a.b = b; 
  6.  
  7. JSON.stringify(a); 
  8. // => TypeError: cyclic object value 
  9.  
  10. stringifySafe(a); 
  11. // => '{"b":{"a":"[Circular ~]"}}' 

封裝

你可能想用你自己的自定義函數(shù)來(lái)封裝 JSON.stringify。你可以決定你想要它做什么。錯(cuò)誤應(yīng)該冒出來(lái)嗎?如果 JSON.stringify 返回 undefined,應(yīng)該怎么做?

例如,Signal Desktop有一個(gè)名為 reallyJsonStringify 的函數(shù),它總是返回一個(gè)用于調(diào)試的字符串。就像這樣

  1. function reallyJsonStringify(value) { 
  2.   let result; 
  3.   try { 
  4.     result = JSON.stringify(value); 
  5.   } catch (_err) { 
  6.     // If there's any error, treat it like `undefined`. 
  7.     result = undefined; 
  8.   } 
  9.  
  10.   if (typeof result === "string") { 
  11.     // It's a string, so we're good. 
  12.     return result; 
  13.   } else { 
  14.     // Convert it to a string. 
  15.     return Object.prototype.toString.call(value); 
  16.   } 

關(guān)于TypeScript類型的說(shuō)明

如果你已經(jīng)在用 TypeScript,可能會(huì)驚訝地發(fā)現(xiàn),TypeScript對(duì) JSON.stringify的官方定義在這里并不正確。它們實(shí)際上看起來(lái)像這樣:

  1. // Note: 這里面簡(jiǎn)化過(guò) 
  2. interface JSON { 
  3.   // ... 
  4.   stringify(value: any): string; 

不幸的是,這是一個(gè)長(zhǎng)期存在的問(wèn)題,沒(méi)有一個(gè)完美的解決方案。

你可以嘗試修補(bǔ) JSON.stringify 的類型,但每個(gè)解決方案都有一定的缺點(diǎn)。我建議用自定義類型定義自己的包裝器并。例如,Signal Desktop的reallyJsonStringify 的模板:

  1. function reallyJsonStringify(value: unknown): string { 
  2.   // ... 

總結(jié)

  • JSON.stringify 有時(shí)會(huì)返回 undefined,而不是一個(gè)字符串
  • JSON.stringify 有時(shí)會(huì)拋出一個(gè)錯(cuò)誤
  • 我們可以通過(guò)用不同的方式包裝函數(shù)來(lái)解決這個(gè)問(wèn)題

希望這篇文章能讓你對(duì) JSON.stringify 有更全面的了解。

作者:BlackLivesMatter 譯者:前端小智

來(lái)源:devinduct 原文:https://evanhahn.com/when-stringify-doesnt-return-a-string

 

責(zé)任編輯:姜華 來(lái)源: 大遷世界
相關(guān)推薦

2024-03-25 00:10:00

JSON后端開(kāi)發(fā)

2021-05-06 05:30:33

JSONstringify()parse()

2023-01-17 16:25:18

前端開(kāi)發(fā)JSON

2020-06-12 09:20:33

前端Blob字符串

2020-07-28 08:26:34

WebSocket瀏覽器

2021-12-11 18:59:35

JavascriptJSON應(yīng)用

2022-12-05 14:50:53

2010-08-23 09:56:09

Java性能監(jiān)控

2019-06-11 15:25:03

JSON性能前端

2011-09-15 17:10:41

2022-10-13 11:48:37

Web共享機(jī)制操作系統(tǒng)

2009-12-10 09:37:43

2021-02-01 23:23:39

FiddlerCharlesWeb

2020-03-29 20:16:09

JavaScript前端技術(shù)

2020-05-25 14:37:31

JSON.string前端秘密特性

2021-12-29 11:38:59

JS前端沙箱

2012-11-23 10:57:44

Shell

2015-06-19 13:54:49

2020-08-11 11:20:49

Linux命令使用技巧

2021-10-17 13:10:56

函數(shù)TypeScript泛型
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)