91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

javascript中JSON.stringify如何使用

發布時間:2022-03-11 09:38:12 來源:億速云 閱讀:180 作者:小新 欄目:web開發

小編給大家分享一下javascript中JSON.stringify如何使用,希望大家閱讀完這篇文章之后都有所收獲,下面讓我們一起去探討吧!

javascript中JSON.stringify如何使用

三參數

在日常編程中,我們經常 JSON.stringify 方法將某個對象轉換成 JSON 字符串形式。

const stu = {
    name: 'zcxiaobao',
    age: 18
}

// {"name":"zcxiaobao","age":18}
console.log(JSON.stringify(stu));

stringify 真的就這么簡單嗎?我們先來看一下 MDN 中對 stringify 的定義。

MDN 中指出: JSON.stringify() 方法將一個 JavaScript 對象或值轉換為 JSON 字符串,如果指定了一個 replacer 函數,則可以選擇性地替換值,或者指定的 replacer 是數組,則可選擇性地僅包含數組指定的屬性。

看完定義,小包就一驚,stringfy 不止一個參數嗎?當然了,stringify 有三個參數。

咱們來看一下 stringify 語法和參數介紹:

JSON.stringify(value[, replacer [, space]])
  • value: 將要序列后成 JSON 字符串的值。

  • replacer(可選)

    • 如果該參數是一個函數,則在序列化過程中,被序列化的值的每個屬性都會經過該函數的轉換和處理;

    • 如果該參數是一個數組,則只有包含在這個數組中的屬性名才會被序列化到最終的 JSON 字符串中

    • 如果該參數為 null 或者未提供,則對象所有的屬性都會被序列化。

  • space(可選): 指定縮進用的空白字符串,用于美化輸出

    • 如果參數是個數字,它代表有多少的空格。上限為10。

    • 該值若小于1,則意味著沒有空格

    • 如果該參數為字符串(當字符串長度超過10個字母,取其前10個字母),該字符串將被作為空格

    • 如果該參數沒有提供(或者為 null),將沒有空格

replacer

我們來嘗試一下 replacer 的使用。

  • replacer 作為函數

replacer 作為函數,它有兩個參數,鍵(key) 和 值(value),并且兩個參數都會被序列化。

在開始時,replacer 函數會被傳入一個空字符串作為 key 值,代表著要被 stringify 的這個對象。理解這點很重要,replacer 函數并非是上來就把對象解析成鍵值對形式,而是先傳入了待序列化對象。隨后每個對象或數組上的屬性會被依次傳入。 如果函數返回值為undefined或者函數時,該屬性值會被過濾掉,其余按照返回規則。

// repalcer 接受兩個參數 key value
// key value 分別為對象的每個鍵值對
// 因此我們可以根據鍵或者值的類型進行簡單篩選
function replacer(key, value) {
  if (typeof value === "string") {
    return undefined;
  }
  return value;
}
// function 可自己測試
function replacerFunc(key, value) {
  if (typeof value === "string") {
    return () => {};
  }
  return value;
}
const foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7};
const jsonString = JSON.stringify(foo, replacer);

JSON 序列化結果為 {"week":45,"month":7}

但如果序列化的是數組,若 replacer 函數返回 undefined 或者函數,當前值不會被忽略,而將會被 null 取代。

const list = [1, '22', 3]
const jsonString = JSON.stringify(list, replacer)

JSON 序列化的結果為 '[1,null,3]'

  • replacer 作為數組

作為數組比較好理解,過濾數組中出現的鍵值。

const foo = {foundation: "Mozilla", model: "box", week: 45, transport: "car", month: 7};
const jsonString = JSON.stringify(foo, ['week', 'month']);

JSON 序列化結果為 {"week":45,"month":7}, 只保留 weekmonth 屬性值。

九特性

特性一: undefined、函數、Symbol值

  • 出現在非數組對象屬性值中: undefined、任意函數、Symbol 值在序列化過程中將會被忽略

  • 出現在數組中: undefined、任意函數、Symbol值會被轉化為 null

  • 單獨轉換時: 會返回 undefined

// 1. 對象屬性值中存在這三種值會被忽略
const obj = {
  name: 'zc',
  age: 18,
  // 函數會被忽略
  sayHello() {
    console.log('hello world')
  },
  // undefined會被忽略
  wife: undefined,
  // Symbol值會被忽略
  id: Symbol(111),
  // [Symbol('zc')]: 'zc',
}
// 輸出結果: {"name":"zc","age":18}
console.log(JSON.stringify(obj));

// 2. 數組中這三種值會被轉化為 null
const list = [
  'zc', 
  18, 
  // 函數轉化為 null
  function sayHello() {
    console.log('hello world')
  }, 
  // undefined 轉換為 null
  undefined, 
  // Symbol 轉換為 null
  Symbol(111)
]

// ["zc",18,null,null,null]
console.log(JSON.stringify(list))

// 3. 這三種值單獨轉化將會返回 undefined

console.log(JSON.stringify(undefined))  // undefined
console.log(JSON.stringify(Symbol(111))) // undefined
console.log(JSON.stringify(function sayHello() { 
  console.log('hello world')
})) // undefined

特性二: toJSON() 方法

轉換值如果有 toJSON() 方法,toJSON() 方法返回什么值,序列化結果就返回什么值,其余值會被忽略。

const obj = {
  name: 'zc',
  toJSON(){
    return 'return toJSON'
  }
}
// return toJSON
console.log(JSON.stringify(obj));

特性三: 布爾值、數字、字符串的包裝對象

布爾值、數字、字符串的包裝對象在序列化過程中會自動轉換成對應的原始值

JSON.stringify([new Number(1), new String("zcxiaobao"), new Boolean(true)]);
// [1,"zcxiaobao",true]

特性四: NaN Infinity null

特性四主要針對 JavaScript 里面的特殊值,例如 Number 類型里的 NaNInfinity 及 null 。此三種數值序列化過程中都會被當做 null

// [null,null,null,null,null]
JSON.stringify([null, NaN, -NaN, Infinity, -Infinity])

// 特性三講過布爾值、數字、字符串的包裝對象在序列化過程中會自動轉換成對應的原始值
// 隱式類型轉換就會調用包裝類,因此會先調用 Number => NaN
// 之后再轉化為 null
// 1/0 => Infinity => null
JSON.stringify([Number('123a'), +'123a', 1/0])

特性五: Date對象

Date 對象上部署了 toJSON 方法(同 Date.toISOString())將其轉換為字符串,因此 JSON.stringify() 將會序列化 Date 的值為時間格式字符串

// "2022-03-06T08:24:56.138Z"
JSON.stringify(new Date())

特性六: Symbol

特性一提到,Symbol 類型當作值來使用時,對象、數組、單獨使用分別會被忽略、轉換為 null 、轉化為 undefined

同樣的,所有以 Symbol 為屬性鍵的屬性都會被完全忽略掉,即便 replacer 參數中強制指定包含了它們

const obj = {
  name: 'zcxiaobao',
  age: 18,
  [Symbol('lyl')]: 'unique'
}
function replacer(key, value) {
  if (typeof key === 'symbol') {
    return value;
  }
}

// undefined
JSON.stringify(obj, replacer);

通過上面案例,我們可以看出,雖然我們通過 replacer 強行指定了返回 Symbol 類型值,但最終還是會被忽略掉。

特性七: BigInt

JSON.stringify 規定: 嘗試去轉換 BigInt 類型的值會拋出 TypeError

const bigNumber = BigInt(1)
// Uncaught TypeError: Do not know how to serialize a BigInt
console.log(JSON.stringify(bigNumber))

特性八: 循環引用

特性八指出: 對包含循環引用的對象(對象之間相互引用,形成無限循環)執行此方法,會拋出錯誤

日常開發中深拷貝最簡單暴力的方式就是使用 JSON.parse(JSON.stringify(obj)),但此方法下的深拷貝存在巨坑,關鍵問題就在于 stringify 無法處理循環引用問題。

const obj = {
  name: 'zcxiaobao',
  age: 18,
}

const loopObj = {
  obj
}
// 形成循環引用
obj.loopObj = loopObj;
JSON.stringify(obj)

/* Uncaught TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Object'
    |     property 'loopObj' -> object with constructor 'Object'
    --- property 'obj' closes the circle
    at JSON.stringify (<anonymous>)
    at <anonymous>:10:6
*/

特性九: 可枚舉屬性

對于對象(包括 Map/Set/WeakMap/WeakSet)的序列化,除了上文講到的一些情況,stringify 也明確規定,僅會序列化可枚舉的屬性

// 不可枚舉的屬性默認會被忽略
// {"age":18}
JSON.stringify(
    Object.create(
        null,
        {
            name: { value: 'zcxiaobao', enumerable: false },
            age: { value: 18, enumerable: true }
        }
    )
);

六妙用

localStorage

localStorage 對象用于長久保存整個網站的數據,保存的數據沒有過期時間,直到手動去刪除。通常我們以對象形式進行存儲。

  • 單純調用 localStorage 對象方法

const obj = {
  name: 'zcxiaobao',
  age: 18
}
// 單純調用 localStorage.setItem()

localStorage.setItem('zc', obj);

// 最終返回結果是 [object Object]
// 可見單純調用localStorage是失敗的
console.log(localStorage.getItem('zc'))
  • localStorage 配合 JSON.stringify 方法

localStorage.setItem('zc', JSON.stringify(obj));

// 最終返回結果是 {name: 'zcxiaobao', age: 18}
console.log(JSON.parse(localStorage.getItem('zc')))

屬性過濾

來假設這樣一個場景,后端返回了一個很長的對象,對象里面屬性很多,而我們只需要其中幾個屬性,并且這幾個屬性我們要存儲到 localStorage 中。

  • 方案一: 解構賦值+ stringify

// 我們只需要 a,e,f 屬性
const obj = {
  a:1, b:2, c:3, d:4, e:5, f:6, g:7
}
// 解構賦值
const {a,e,f} = obj;
// 存儲到localStorage
localStorage.setItem('zc', JSON.stringify({a,e,f}))
// {"a":1,"e":5,"f":6}
console.log(localStorage.getItem('zc'))
  • 使用 stringifyreplacer 參數

// 借助 replacer 作為數組形式進行過濾
localStorage.setItem('zc', JSON.stringify(obj, ['a','e','f']))
// {"a":1,"e":5,"f":6}
console.log(localStorage.getItem('zc'))

replacer 是數組時,可以簡單的過濾出我們所需的屬性,是一個不錯的小技巧。

三思而后行之深拷貝

使用 JSON.parse(JSON.stringify) 是實現對象的深拷貝最簡單暴力的方法之一。但也正如標題所言,使用該種方法的深拷貝要深思熟慮。

  • 循環引用問題,stringify 會報錯

  • 函數、undefinedSymbol 會被忽略

  • NaNInfinity-Infinity 會被序列化成 null

  • ...

因此在使用 JSON.parse(JSON.stringify) 做深拷貝時,一定要深思熟慮。如果沒有上述隱患,JSON.parse(JSON.stringify) 是一個可行的深拷貝方案。

對象的 map 函數

在使用數組進行編程時,我們會經常使用到 map 函數。有了 replacer 參數后,我們就可以借助此參數,實現對象的 map 函數。

const ObjectMap = (obj, fn) => {
  if (typeof fn !== "function") {
    throw new TypeError(`${fn} is not a function !`);
  }
  // 先調用 JSON.stringify(obj, replacer) 實現 map 功能
  // 然后調用 JSON.parse 重新轉化成對象
  return JSON.parse(JSON.stringify(obj, fn));
};

// 例如下面給 obj 對象的屬性值乘以2

const obj = {
  a: 1,
  b: 2,
  c: 3
}
console.log(ObjectMap(obj, (key, val) => {
  if (typeof value === "number") {
    return value * 2;
  }
  return value;
}))

很多同學有可能會很奇怪,為什么里面還需要多加一部判斷,直接 return value * 2 不可嗎?

上文講過,replacer 函數首先傳入的是待序列化對象,對象 * 2 => NaN => toJSON(NaN) => undefined => 被忽略,就沒有后續的鍵值對解析了。

刪除對象屬性

借助 replacer 函數,我們還可以刪除對象的某些屬性。

const obj = {
  name: 'zcxiaobao',
  age: 18
}
// {"age":18}
JSON.stringify(obj, (key, val) => {
  // 返回值為 undefined時,該屬性會被忽略 
  if (key === 'name') {
    return undefined;
  }
  return val;
})

對象判斷

JSON.stringify 可以將對象序列化為字符串,因此我們可以借助字符串的方法來實現簡單的對象相等判斷。

//判斷數組是否包含某對象
const names = [
  {name:'zcxiaobao'},
  {name:'txtx'},
  {name:'mymy'},
];
const zcxiaobao = {name:'zcxiaobao'};
// true
JSON.stringify(names).includes(JSON.stringify(zcxiaobao))
 
// 判斷對象是否相等
const d1 = {type: 'div'}
const d2 = {type: 'div'}

// true
JSON.stringify(d1) === JSON.stringify(d2);
數組對象去重

借助上面的思想,我們還能實現簡單的數組對象去重。

但由于 JSON.stringify 序列化 {x:1, y:1}{y:1, x:1} 結果不同,因此在開始之前我們需要處理一下數組中的對象。

  • 方法一: 將數組中的每個對象的鍵按字典序排列

arr.forEach(item => {
  const newItem = {};
  Object.keys(item)   // 獲取對象鍵值
        .sort()       // 鍵值排序
        .map(key => { // 生成新對象
          newItem[key] = item[key];
        })
  // 使用 newItem 進行去重操作
})

但方法一有些繁瑣,JSON.stringify 提供了 replacer 數組格式參數,可以過濾數組。

  • 方法二: 借助 replacer 數組格式

function unique(arr) {
  const keySet = new Set();
  const uniqueObj = {}
  // 提取所有的鍵
  arr.forEach(item => {
    Object.keys(item).forEach(key => keySet.add(key))
  })
  const replacer = [...keySet];
  arr.forEach(item => {
    // 所有的對象按照規定鍵值 replacer 過濾
    unique[JSON.stringify(item, replacer)] = item;
  })
  return Object.keys(unique).map(u => JSON.parse(u))
}

// 測試一下
unique([{}, {}, 
      {x:1},
      {x:1},
      {a:1},
      {x:1,a:1},
      {x:1,a:1},
      {x:1,a:1,b:1}
      ])

// 返回結果
[{},{"x":1},{"a":1},{"x":1,"a":1},{"x":1,"a":1,"b":1}]

看完了這篇文章,相信你對“javascript中JSON.stringify如何使用”有了一定的了解,如果想了解更多相關知識,歡迎關注億速云行業資訊頻道,感謝各位的閱讀!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

黄大仙区| 杭锦后旗| 广南县| 涞源县| 永清县| 浦江县| 修武县| 竹北市| 庄浪县| 德格县| 上栗县| 巴彦淖尔市| 育儿| 洪湖市| 鄂州市| 邯郸市| 三穗县| 微山县| 六盘水市| 马龙县| 蒙自县| 临夏县| 上思县| 景洪市| 平和县| 满城县| 叙永县| 右玉县| 南部县| 洪泽县| 水城县| 如东县| 台山市| 长治市| 封丘县| 巨鹿县| 卫辉市| 新龙县| 莎车县| 金溪县| 松滋市|