欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

學(xué)習(xí)JSON.stringify的9大特性和轉(zhuǎn)換規(guī)則

 更新時(shí)間:2022年02月14日 11:14:47   作者:前端胖頭魚  
本文介紹JSON.stringify9大特性和轉(zhuǎn)換規(guī)則,JSON.stringify()方法將一個(gè)JavaScript對(duì)象或值轉(zhuǎn)換為?JSON?字符串,如果指定了一個(gè)replacer?函數(shù),則可以選擇性地替換值,或者指定的replacer是數(shù)組,則可選擇性地僅包含數(shù)組指定的屬性,更多內(nèi)容需要的小火煸可以參考下面溫行內(nèi)容

一、JSON.stringify介紹

JSON.stringify()  方法將一個(gè) JavaScript 對(duì)象或值轉(zhuǎn)換為 JSON 字符串,如果指定了一個(gè) replacer 函數(shù),則可以選擇性地替換值,或者指定的 replacer 是數(shù)組,則可選擇性地僅包含數(shù)組指定的屬性。

語(yǔ)法:

JSON.stringify(value[, replacer [, space]])

參數(shù):

value 將要序列化成 一個(gè) JSON 字符串的值。

replacer 可選

  • 如果該參數(shù)是一個(gè)函數(shù),則在序列化過(guò)程中,被序列化的值的每個(gè)屬性都會(huì)經(jīng)過(guò)該函數(shù)的轉(zhuǎn)換和處理;
  • 如果該參數(shù)是一個(gè)數(shù)組,則只有包含在這個(gè)數(shù)組中的屬性名才會(huì)被序列化到最終的 JSON 字符串中;
  • 如果該參數(shù)為 null 或者未提供,則對(duì)象所有的屬性都會(huì)被序列化。

space 可選

  • 指定縮進(jìn)用的空白字符串,用于美化輸出(pretty-print);
  • 如果參數(shù)是個(gè)數(shù)字,它代表有多少的空格;上限為10。
  • 該值若小于1,則意味著沒(méi)有空格;
  • 如果該參數(shù)為字符串(當(dāng)字符串長(zhǎng)度超過(guò)10個(gè)字母,取其前10個(gè)字母),該字符串將被作為空格;
  • 如果該參數(shù)沒(méi)有提供(或者為 null),將沒(méi)有空格。

返回值:

一個(gè)表示給定值的JSON字符串。

異常:

  • 當(dāng)在循環(huán)引用時(shí)會(huì)拋出異常TypeError ("cyclic object value")(循環(huán)對(duì)象值)
  • 當(dāng)嘗試去轉(zhuǎn)換 BigInt 類型的值會(huì)拋出TypeError ("BigInt value can't be serialized in JSON")(BigInt值不能JSON序列化).

基本使用:

注意:

  • JSON.stringify可以轉(zhuǎn)換對(duì)象或者值(平常用的更多的是轉(zhuǎn)換對(duì)象)
  • 可以指定replacer為函數(shù)選擇性的地替換
  • 也可以指定replacer為數(shù)組,可轉(zhuǎn)換指定的屬性

這里僅僅是MDN上關(guān)于JSON.stringify其中最基礎(chǔ)的說(shuō)明,咱們先打個(gè)碼試試這幾個(gè)特性

1. 轉(zhuǎn)換對(duì)象

console.log(JSON.stringify({ name: '前端胖頭魚', sex: 'boy' })) // '{"name":"前端胖頭魚","sex":"boy"}'

 2. 轉(zhuǎn)換普通值

console.log(JSON.stringify('前端胖頭魚')) // "前端胖頭魚"
console.log(JSON.stringify(1)) // "1"
console.log(JSON.stringify(true)) // "true"
console.log(JSON.stringify(null)) // "null"

3. 指定replacer函數(shù)

console.log(JSON.stringify({ name: '前端胖頭魚', sex: 'boy', age: 100 }, (key, value) => {
? return typeof value === 'number' ? undefined : value
}))
// '{"name":"前端胖頭魚","sex":"boy"}'

4. 指定數(shù)組

console.log(JSON.stringify({ name: '前端胖頭魚', sex: 'boy', age: 100 }, [ 'name' ]))
// '{"name":"前端胖頭魚"}'

 5. 指定space(美化輸出)

console.log(JSON.stringify({ name: '前端胖頭魚', sex: 'boy', age: 100 }))
// '{"name":"前端胖頭魚","sex":"boy","age":100}'
console.log(JSON.stringify({ name: '前端胖頭魚', sex: 'boy', age: 100 }, null , 2))
/*
{
? "name": "前端胖頭魚",
? "sex": "boy",
? "age": 100
}
*/

二、9大特性要記住

以前僅僅是使用了這個(gè)方法,卻沒(méi)有詳細(xì)了解他的轉(zhuǎn)換規(guī)則,居然有9個(gè)之多。

特性一

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

// 1. 對(duì)象中存在這三種值會(huì)被忽略
console.log(JSON.stringify({
? name: '前端胖頭魚',
? sex: 'boy',
? // 函數(shù)會(huì)被忽略
? showName () {
? ? console.log('前端胖頭魚')
? },
? // undefined會(huì)被忽略
? age: undefined,
? // Symbol會(huì)被忽略
? symbolName: Symbol('前端胖頭魚')
}))
// '{"name":"前端胖頭魚","sex":"boy"}'

// 2. 數(shù)組中存在著三種值會(huì)被轉(zhuǎn)化為null
console.log(JSON.stringify([
? '前端胖頭魚',
? 'boy',
? // 函數(shù)會(huì)被轉(zhuǎn)化為null
? function showName () {
? ? console.log('前端胖頭魚')
? },
? //undefined會(huì)被轉(zhuǎn)化為null
? undefined,
? //Symbol會(huì)被轉(zhuǎn)化為null
? Symbol('前端胖頭魚')
]))
// '["前端胖頭魚","boy",null,null,null]'

// 3.單獨(dú)轉(zhuǎn)換會(huì)返回undefined
console.log(JSON.stringify(
? function showName () {
? ? console.log('前端胖頭魚')
? }
)) // undefined
console.log(JSON.stringify(undefined)) // undefined
console.log(JSON.stringify(Symbol('前端胖頭魚'))) // undefined

特性二

布爾值、數(shù)字、字符串的包裝對(duì)象在序列化過(guò)程中會(huì)自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的原始值。

console.log(JSON.stringify([new Number(1), new String("前端胖頭魚"), new Boolean(false)]))
// '[1,"前端胖頭魚",false]'

特性三

所有以symbol為屬性鍵的屬性都會(huì)被完全忽略掉,即便 replacer 參數(shù)中強(qiáng)制指定包含了它們。

console.log(JSON.stringify({
? [Symbol('前端胖頭魚')]: '前端胖頭魚'}
))?
// '{}'
console.log(JSON.stringify({
? [ Symbol('前端胖頭魚') ]: '前端胖頭魚',
}, (key, value) => {
? if (typeof key === 'symbol') {
? ? return value
? }
}))
// undefined

特性四

NaNInfinity 格式的數(shù)值及 null 都會(huì)被當(dāng)做 null。

console.log(JSON.stringify({
? age: NaN,
? age2: Infinity,
? name: null
}))
// '{"age":null,"age2":null,"name":null}'

特性五

轉(zhuǎn)換值如果有toJSON() 方法,該方法定義什么值將被序列化。

const toJSONObj = {
? name: '前端胖頭魚',
? toJSON () {
? ? return 'JSON.stringify'
? }
}

console.log(JSON.stringify(toJSONObj))
// "JSON.stringify"

特性六

Date 日期調(diào)用了 toJSON() 將其轉(zhuǎn)換為了 string 字符串(同Date.toISOString()),因此會(huì)被當(dāng)做字符串處理。

const d = new Date()

console.log(d.toJSON()) // 2021-10-05T14:01:23.932Z
console.log(JSON.stringify(d)) // "2021-10-05T14:01:23.932Z"

特性七

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

let cyclicObj = {
? name: '前端胖頭魚',
}

cyclicObj.obj = cyclicObj

console.log(JSON.stringify(cyclicObj))
// Converting circular structure to JSON

特性八

其他類型的對(duì)象,包括Map/Set/WeakMap/WeakSet,僅會(huì)序列化可枚舉的屬性

let enumerableObj = {}

Object.defineProperties(enumerableObj, {
? name: {
? ? value: '前端胖頭魚',
? ? enumerable: true
? },
? sex: {
? ? value: 'boy',
? ? enumerable: false
? },
})

console.log(JSON.stringify(enumerableObj))
// '{"name":"前端胖頭魚"}'

特性九

當(dāng)嘗試去轉(zhuǎn)換 BigInt 類型的值會(huì)拋出錯(cuò)誤

const alsoHuge = BigInt(9007199254740991)

console.log(JSON.stringify(alsoHuge))
// TypeError: Do not know how to serialize a BigInt

三、手寫一個(gè)JSON.stringify

終于重新學(xué)完JSON.stringify的眾多特性啦!咱們根據(jù)這些特性來(lái)手寫一個(gè)簡(jiǎn)單版本的吧(無(wú)replacer函數(shù)和space)

源碼實(shí)現(xiàn):

const jsonstringify = (data) => {
? // 確認(rèn)一個(gè)對(duì)象是否存在循環(huán)引用
? const isCyclic = (obj) => {
? // 使用Set數(shù)據(jù)類型來(lái)存儲(chǔ)已經(jīng)檢測(cè)過(guò)的對(duì)象
? let stackSet = new Set()
? let detected = false

? const detect = (obj) => {
? ? // 不是對(duì)象類型的話,可以直接跳過(guò)
? ? if (obj && typeof obj != 'object') {
? ? ? return
? ? }
? ? // 當(dāng)要檢查的對(duì)象已經(jīng)存在于stackSet中時(shí),表示存在循環(huán)引用
? ? if (stackSet.has(obj)) {
? ? ? return detected = true
? ? }
? ? // 將當(dāng)前obj存如stackSet
? ? stackSet.add(obj)

? ? for (let key in obj) {
? ? ? // 對(duì)obj下的屬性進(jìn)行挨個(gè)檢測(cè)
? ? ? if (obj.hasOwnProperty(key)) {
? ? ? ? detect(obj[key])
? ? ? }
? ? }
? ? // 平級(jí)檢測(cè)完成之后,將當(dāng)前對(duì)象刪除,防止誤判
? ? /*
? ? ? 例如:對(duì)象的屬性指向同一引用,如果不刪除的話,會(huì)被認(rèn)為是循環(huán)引用
? ? ? let tempObj = {
? ? ? ? name: '前端胖頭魚'
? ? ? }
? ? ? let obj4 = {
? ? ? ? obj1: tempObj,
? ? ? ? obj2: tempObj
? ? ? }
? ? */
? ? stackSet.delete(obj)
? }

? detect(obj)

? return detected
}

? // 特性七:
? // 對(duì)包含循環(huán)引用的對(duì)象(對(duì)象之間相互引用,形成無(wú)限循環(huán))執(zhí)行此方法,會(huì)拋出錯(cuò)誤。
? if (isCyclic(data)) {
? ? throw new TypeError('Converting circular structure to JSON')
? }

? // 特性九:
? // 當(dāng)嘗試去轉(zhuǎn)換 BigInt 類型的值會(huì)拋出錯(cuò)誤
? if (typeof data === 'bigint') {
? ? throw new TypeError('Do not know how to serialize a BigInt')
? }

? const type = typeof data
? const commonKeys1 = ['undefined', 'function', 'symbol']
? const getType = (s) => {
? ? return Object.prototype.toString.call(s).replace(/\[object (.*?)\]/, '$1').toLowerCase()
? }

? // 非對(duì)象
? if (type !== 'object' || data === null) {
? ? let result = data
? ? // 特性四:
? ? // NaN 和 Infinity 格式的數(shù)值及 null 都會(huì)被當(dāng)做 null。
? ? if ([NaN, Infinity, null].includes(data)) {
? ? ? result = 'null'
? ? ? // 特性一:
? ? ? // `undefined`、`任意的函數(shù)`以及`symbol值`被`單獨(dú)轉(zhuǎn)換`時(shí),會(huì)返回 undefined
? ? } else if (commonKeys1.includes(type)) {
? ? ? // 直接得到undefined,并不是一個(gè)字符串'undefined'
? ? ? return undefined
? ? } else if (type === 'string') {
? ? ? result = '"' + data + '"'
? ? }

? ? return String(result)
? } else if (type === 'object') {
? ? // 特性五:
? ? // 轉(zhuǎn)換值如果有 toJSON() 方法,該方法定義什么值將被序列化
? ? // 特性六:
? ? // Date 日期調(diào)用了 toJSON() 將其轉(zhuǎn)換為了 string 字符串(同Date.toISOString()),因此會(huì)被當(dāng)做字符串處理。
? ? if (typeof data.toJSON === 'function') {
? ? ? return jsonstringify(data.toJSON())
? ? } else if (Array.isArray(data)) {
? ? ? let result = data.map((it) => {
? ? ? ? // 特性一:
? ? ? ? // `undefined`、`任意的函數(shù)`以及`symbol值`出現(xiàn)在`數(shù)組`中時(shí)會(huì)被轉(zhuǎn)換成?`null`
? ? ? ? return commonKeys1.includes(typeof it) ? 'null' : jsonstringify(it)
? ? ? })

? ? ? return `[${result}]`.replace(/'/g, '"')
? ? } else {
? ? ? // 特性二:
? ? ? // 布爾值、數(shù)字、字符串的包裝對(duì)象在序列化過(guò)程中會(huì)自動(dòng)轉(zhuǎn)換成對(duì)應(yīng)的原始值。
? ? ? if (['boolean', 'number'].includes(getType(data))) {
? ? ? ? return String(data)
? ? ? } else if (getType(data) === 'string') {
? ? ? ? return '"' + data + '"'
? ? ? } else {
? ? ? ? let result = []
? ? ? ? // 特性八
? ? ? ? // 其他類型的對(duì)象,包括 Map/Set/WeakMap/WeakSet,僅會(huì)序列化可枚舉的屬性
? ? ? ? Object.keys(data).forEach((key) => {
? ? ? ? ? // 特性三:
? ? ? ? ? // 所有以symbol為屬性鍵的屬性都會(huì)被完全忽略掉,即便 replacer 參數(shù)中強(qiáng)制指定包含了它們。
? ? ? ? ? if (typeof key !== 'symbol') {
? ? ? ? ? ? const value = data[key]
? ? ? ? ? ? // 特性一
? ? ? ? ? ? // `undefined`、`任意的函數(shù)`以及`symbol值`,出現(xiàn)在`非數(shù)組對(duì)象`的屬性值中時(shí)在序列化過(guò)程中會(huì)被忽略
? ? ? ? ? ? if (!commonKeys1.includes(typeof value)) {
? ? ? ? ? ? ? result.push(`"${key}":${jsonstringify(value)}`)
? ? ? ? ? ? }
? ? ? ? ? }
? ? ? ? })

? ? ? ? return `{${result}}`.replace(/'/, '"')
? ? ? }
? ? }
? }
}

測(cè)試一把:

// 1. 測(cè)試一下基本輸出
console.log(jsonstringify(undefined)) // undefined?
console.log(jsonstringify(() => { })) // undefined
console.log(jsonstringify(Symbol('前端胖頭魚'))) // undefined
console.log(jsonstringify((NaN))) // null
console.log(jsonstringify((Infinity))) // null
console.log(jsonstringify((null))) // null
console.log(jsonstringify({
? name: '前端胖頭魚',
? toJSON() {
? ? return {
? ? ? name: '前端胖頭魚2',
? ? ? sex: 'boy'
? ? }
? }
}))
// {"name":"前端胖頭魚2","sex":"boy"}

// 2. 和原生的JSON.stringify轉(zhuǎn)換進(jìn)行比較
console.log(jsonstringify(null) === JSON.stringify(null));
// true
console.log(jsonstringify(undefined) === JSON.stringify(undefined));
// true
console.log(jsonstringify(false) === JSON.stringify(false));
// true
console.log(jsonstringify(NaN) === JSON.stringify(NaN));
// true
console.log(jsonstringify(Infinity) === JSON.stringify(Infinity));
// true
let str = "前端胖頭魚";
console.log(jsonstringify(str) === JSON.stringify(str));
// true
let reg = new RegExp("\w");
console.log(jsonstringify(reg) === JSON.stringify(reg));
// true
let date = new Date();
console.log(jsonstringify(date) === JSON.stringify(date));
// true
let sym = Symbol('前端胖頭魚');
console.log(jsonstringify(sym) === JSON.stringify(sym));
// true
let array = [1, 2, 3];
console.log(jsonstringify(array) === JSON.stringify(array));
// true
let obj = {
? name: '前端胖頭魚',
? age: 18,
? attr: ['coding', 123],
? date: new Date(),
? uni: Symbol(2),
? sayHi: function () {
? ? console.log("hello world")
? },
? info: {
? ? age: 16,
? ? intro: {
? ? ? money: undefined,
? ? ? job: null
? ? }
? },
? pakingObj: {
? ? boolean: new Boolean(false),
? ? string: new String('前端胖頭魚'),
? ? number: new Number(1),
? }
}
console.log(jsonstringify(obj) === JSON.stringify(obj))?
// true
console.log((jsonstringify(obj)))
// {"name":"前端胖頭魚","age":18,"attr":["coding",123],"date":"2021-10-06T14:59:58.306Z","info":{"age":16,"intro":{"job":null}},"pakingObj":{"boolean":false,"string":"前端胖頭魚","number":1}}
console.log(JSON.stringify(obj))
// {"name":"前端胖頭魚","age":18,"attr":["coding",123],"date":"2021-10-06T14:59:58.306Z","info":{"age":16,"intro":{"job":null}},"pakingObj":{"boolean":false,"string":"前端胖頭魚","number":1}}

// 3. 測(cè)試可遍歷對(duì)象
let enumerableObj = {}

Object.defineProperties(enumerableObj, {
? name: {
? ? value: '前端胖頭魚',
? ? enumerable: true
? },
? sex: {
? ? value: 'boy',
? ? enumerable: false
? },
})

console.log(jsonstringify(enumerableObj))
// {"name":"前端胖頭魚"}

// 4. 測(cè)試循環(huán)引用和Bigint

let obj1 = { a: 'aa' }
let obj2 = { name: '前端胖頭魚', a: obj1, b: obj1 }
obj2.obj = obj2

console.log(jsonstringify(obj2))
// TypeError: Converting circular structure to JSON
console.log(jsonStringify(BigInt(1)))
// TypeError: Do not know how to serialize a BigInt

通過(guò)上面測(cè)試可以看出,jsonstringify基本和JSON.stringify表現(xiàn)一致,

到此這篇關(guān)于學(xué)習(xí)JSON.stringify的9大特性和轉(zhuǎn)換規(guī)則的文章就介紹到這了,更多相關(guān)JSON.stringify內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論