亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

怎么使用JSON?stringify及parse方法實現數據深拷貝

發布時間:2022-08-17 16:38:39 來源:億速云 閱讀:126 作者:iii 欄目:開發技術

這篇“怎么使用JSON stringify及parse方法實現數據深拷貝”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“怎么使用JSON stringify及parse方法實現數據深拷貝”文章吧。

    引言

    JSON 的 stringifyparse 兩個方法在平時的工作中也很常用,如果沒有一些特殊的類型,是實現數據深拷貝的一個原生方式。

    下面就這兩個方法的一個手動實現思路。

    JSON.stringify

    JSON.stringify 方法用于將 JavaScript 值轉換為 JSON 字符串。該方法有三個參數:

    • data: 需要轉換的數據

    • replacer:用于轉換結果的對象或者數組,可以函數或者數組

    • space:文本添加縮進、空格和換行符,可以是數字或者字符串,數字的最大值是 10,字符串的最大長度是 10

    下面的測試只用到這些類型:

    number,string,function,object,array,null,undefined,map,set,weakmap,weakset

    但是 JavaScript 數據的嚴格類型遠遠不止這幾個。

    data

    首先我們用 JSON.stringify 來打印結果:

    const testJson = {
      4: 3,
      n: 1,
      s: 's',
      f: () => { },
      null: null,
      unde: undefined,
      arr: [1, 's', null, undefined, () => { }],
      obj: {
        n: '1',
        s: 's'
      },
      map: new Map(),
      set: new Set([1, 2, 3]),
      wmap: new WeakMap(),
      wset: new WeakSet()
    }
    const raws = JSON.stringify(testJson)
    // {
    //  "4":3,"n":1,"s":"s","null":null,"arr":[1,"s",null,null,null],
    //  "obj":{"n":"1","s":"s"},"map":{},"set":{},"wmap":{},"wset":{}
    // }

    根據上面的結果,我們可以發現對象內的 function, undefined 被剔除了,map, set 等都被動的轉換成了空對象。而數組內的 functionundefined 被替換成了 null

    所以我們可以根據上述規則寫一個簡單的 stringify 方法:

    const stringify = (data: any) => {
      // 獲取數據的嚴格類型
      const type = getType(data)
      let res = ''
      switch (type) {
        case 'Object':
          // 處理對象
          res = stringifyObject(data, indent, replacer, space)
          break
        case 'Array':
          // 處理數組
          res = stringifyArray(data, indent, space)
          break
        case 'Number':
          res = `${data}`
          break
        case 'String':
          res = `"${data}"`
          break
        case 'Null':
          res = 'null'
          break
        case 'Set':
        case 'WeakSet':
        case 'Map':
        case 'WeakMap':
          res = '{}'
          break
        default:
          return
      }
      return res
    }

    實現幾個輔助函數:

    // 獲取嚴格類型
    const getType = (data: any) => {
      return Object.prototype.toString.call(data).slice(8, -1)
    }
    // 處理對象方法
    const stringifyObject = (data: Record<string, any>) => {
      const vals: string[] = []
      for (const key in data) {
        // 遞歸處理
        const val = stringify(data[key])
        // 如果值為 undefined,我們則需要跳過
        if (val !== undefined) {
          vals.push(`"${key}":${val}`)
        }
      }
      return `{${vals.join(',')}}`
    }
    // 處理數組方法
    const stringifyArray = (data: any[]) => {
      const vals: any[] = []
      for (const val of data) {
        // 遞歸處理,如果返回 undefined 則替換為 null
        vals.push(stringify(val) || 'null')
      }
      return `[${vals.join(',')}]`
    }

    到這里就實現了 stringify 的簡單版本。下面可以簡單測試一下:

    const raws = JSON.stringify(testJson)
    const cuss = stringify(testJson)
    console.log(raws === cuss) // true

    后面還有兩個參數,我們先實現第三個,第二個參數的作用等下在實現。

    space

    space 主要是用于添加空格、換行、縮進,但是只要 space 的值是合法的,換行符是默認加上一個的。所以我們要改下 stringify 的方法:

    type Replacer = ((key: string, value: any) => any) | null | (string | number)[]
    export const stringify = (data: any, replacer?: Replacer, space?: number | string, indent = 1) => {
      const type = getType(data)
      if (typeof space === 'number') {
        if (space <= 0) {
          space = undefined
        } else {
          space = Math.min(10, space)
        }
      } else if (typeof space === 'string') {
        space = space.substring(0, 10)
      } else if (space) {
        space = undefined
      }
      let res = ''
      switch (type) {
        case 'Object':
          res = stringifyObject(data, indent, replacer, space)
          break
        case 'Array':
          res = stringifyArray(data, indent, space)
          break
        // 省略部分代碼
      }
      // 省略部分代碼
    }

    對于 space 的不同非法的值,我們可以在控制臺上進行一些簡單的測試就可以得出,像 -1 這種其實是不生效的。

    而我處理的是只能是數字和字符串,數字必須是 1 - 10,字符串的最長長度是 10 位,其余的都重置為 undefined。

    因為像數組和對象的這種嵌套,縮進其實是要跟著動的,這里就新增了 indent 字段,初始為 1,后續遞歸就 + 1。

    // 新增分隔符處理方法
    const handleSeparator = (space: number | string, indent: number, prefix: string = '', suffix: string = '') => {
      let separator = prefix + '\n'
      if (typeof space === 'number') {
        separator += ' '.repeat(space).repeat(indent)
      } else {
        separator += space.repeat(indent)
      }
      return separator + suffix
    }
    // 對象方法修改
    const stringifyObject = (data: Record<string, any>, indent: number, replacer?: Replacer, space?: number | string) => {
      const vals: string[] = []
      for (const key in data) {
        const val = stringify(data[key], null, space, indent + 1)
        if (val !== undefined) {
          vals.push(`"${key}":${space ? ' ' : ''}${val}`)
        }
      }
      // 新增 space 處理
      if (space) {
        const val = vals.join(handleSeparator(space, indent, ','))
        if (!val) {
          return '{}'
        }
        const front = handleSeparator(space, indent, '{')
        const back = handleSeparator(space, indent - 1, '', '}')
        return front + val + back
      }
      return `{${vals.join(',')}}`
    }
    // 數組處理方法
    const stringifyArray = (data: any[], indent: number, space?: number | string) => {
      const vals: any[] = []
      for (const val of data) {
        vals.push(stringify(val) || 'null')
      }
      // 新增 space 處理
      if (space) {
        const front = handleSeparator(space, indent, '[')
        const val = vals.join(handleSeparator(space, indent, ','))
        const back = handleSeparator(space, indent - 1, '', ']')
        return front + val + back
      }
      return `[${vals.join(',')}]`
    }

    replacer

    replacer 參數有兩個類型,數組類型是用來過濾對象類型內的字段,只保留數組內的 key,而函數類型有點奇怪,有點不明白,函數的參數是 key 和 value,初始的 key 為空, value 就是當前的對象的值。

    所以這里我們需要修改兩處地方:

    export const stringify = (data: any, replacer?: Replacer, space?: number | string, indent = 1) => {
      // 如果 replacer 為函數的話,直接返回函數運行后的值
      if (typeof replacer === 'function') {
        return replacer('', data)
      }
      const type = getType(data)
      // 省略部分代碼
    }
    const stringifyObject = (data: Record<string, any>, indent: number, replacer?: Replacer, space?: number | string) => {
      const filter = getType(replacer) === 'Array' ? replacer : null
      const vals: string[] = []
      for (const key in data) {
        const val = stringify(data[key], null, space, indent + 1)
        if (
          val !== undefined &&
          (
            // 如果是數組,則當前的 key 必須是在 replacer 數組內
            !filter ||
            (filter as (string | number)[]).includes(key) ||
            (filter as (string | number)[]).includes(+key)
          )
        ) {
          vals.push(`"${key}":${space ? ' ' : ''}${val}`)
        }
      }
      // 省略部分代碼
    }

    到這里, stringify 的方法差不多了。下面是完整代碼:

    type Replacer = ((key: string, value: any) => any) | null | (string | number)[]
    const getType = (data: any) => {
      return Object.prototype.toString.call(data).slice(8, -1)
    }
    const handleSeparator = (space: number | string, indent: number, prefix: string = '', suffix: string = '') => {
      let separator = prefix + '\n'
      if (typeof space === 'number') {
        separator += ' '.repeat(space).repeat(indent)
      } else {
        separator += space.repeat(indent)
      }
      return separator + suffix
    }
    const stringifyObject = (data: Record<string, any>, indent: number, replacer?: Replacer, space?: number | string) => {
      const filter = getType(replacer) === 'Array' ? replacer : null
      const vals: string[] = []
      for (const key in data) {
        const val = stringify(data[key], null, space, indent + 1)
        if (
          val !== undefined &&
          (
            !filter ||
            (filter as (string | number)[]).includes(key) ||
            (filter as (string | number)[]).includes(+key)
          )
        ) {
          vals.push(`"${key}":${space ? ' ' : ''}${val}`)
        }
      }
      if (space) {
        const val = vals.join(handleSeparator(space, indent, ','))
        if (!val) {
          return '{}'
        }
        const front = handleSeparator(space, indent, '{')
        const back = handleSeparator(space, indent - 1, '', '}')
        return front + val + back
      }
      return `{${vals.join(',')}}`
    }
    const stringifyArray = (data: any[], indent: number, space?: number | string) => {
      const vals: any[] = []
      for (const val of data) {
        vals.push(stringify(val) || 'null')
      }
      if (space) {
        const front = handleSeparator(space, indent, '[')
        const val = vals.join(handleSeparator(space, indent, ','))
        const back = handleSeparator(space, indent - 1, '', ']')
        return front + val + back
      }
      return `[${vals.join(',')}]`
    }
    export const stringify = (data: any, replacer?: Replacer, space?: number | string, indent = 1) => {
      if (typeof replacer === 'function') {
        return replacer('', data)
      }
      const type = getType(data)
      if (typeof space === 'number') {
        if (space <= 0) {
          space = undefined
        } else {
          space = Math.min(10, space)
        }
      } else if (typeof space === 'string') {
        space = space.substring(0, 10)
      } else if (space) {
        space = undefined
      }
      let res = ''
      switch (type) {
        case 'Object':
          res = stringifyObject(data, indent, replacer, space)
          break
        case 'Array':
          res = stringifyArray(data, indent, space)
          break
        case 'Number':
          res = `${data}`
          break
        case 'String':
          res = `"${data}"`
          break
        case 'Null':
          res = 'null'
          break
        case 'Set':
        case 'WeakSet':
        case 'Map':
        case 'WeakMap':
          res = '{}'
          break
        default:
          return
      }
      return res
    }

    JSON.parse

    stringify 方法的實現還是比較簡單的,在一些筆試中還有可能會有相關需要實現的題。

    JSON.parse 則是需要將合法的 json 字符串轉換成對象,這里就需要用到一個概念:有限狀態自動機

    有限狀態自動機

    這里只做簡單的介紹:有限狀態機(Finite State Machine),是指任意時刻都處于有限狀態集合中的某一狀態。當其獲得一個輸入字符時,將從當前狀態轉換到另一個狀態或者仍然保持當前狀態。

    可以結合當前 json 字符串的場景來簡單理解一下:

    我們有如下一個字符串:

    const str = '{"4":3,"s":"s","null":null,"arr":[1,"s",null],"obj":{}}'

    然后定義幾個狀態:

    const State = {
      INIT: 'INIT',  // 初始狀態
      OBJECTSTART: 'OBJECTSTART',  // 開始解析對象
      ARRAYSTART: 'ARRAYSTART',  // 開始解析數組
      OBJVALSTART: 'OBJVALSTART',  // 開始解析對象的屬性與值
      OBJVALEND: 'OBJVALEND',  // 對象屬性與值解析結束
      ARRVALSTART: 'ARRVALSTART' // 開始解析數組值
    }

    因為 json 字符串是非常規則的字符串,所以我們可以結合正則表達式來提取相關步驟的數據,在字符串中的 ' '\t\n\r 等也是可以的,所以在正則中需要考慮并且替換。

    const parse = (data: string | number | null) => {
      if (typeof data === 'number' || data === null) {
        return data
      }
      // 將字符串轉換為地址引用,方便后面字符串數據的消費
      const context = { data }
      // 具體解析方法
      return parseData(context)
    }

    然后定義幾個輔助函數:

    // 字符串的消費函數 - 就是截取已匹配完的數據,返回剩余字符串
    const advance = (context: { data: string }, num: number) => {
      context.data = context.data.slice(num)
    }
    // 是否結束狀態機
    const isEnd = (ctx: { data: string }) => {
      // 如果沒有數據了,則結束
      if (!ctx.data) {
        return false
      }
      const match = /^(}|\])[ \t\n\r]*/.exec(ctx.data)
      if (match) {
        if (
          match[1] === '}' && getType(res) !== 'Object' ||
          match[1] === ']' && getType(res) !== 'Array'
        ) {
          throw Error('解析錯誤')
        }
        advance(ctx, match[0].length)
        return false
      }
      return true
    }
    // 解析對象屬性值
    const parseObjValue = (context: { data: string }) => {
      const match = /^[ \n\t\r]*((".*?")|([0-9A-Za-z]*))[ \t\n\r]?/.exec(context.data)
      if (match) {
        advance(context, match[0].length)
        const valMatch = /^"(.*?)"$/.exec(match[1])
        if (valMatch) {
          return valMatch[1]
        }
        if (match[1] === 'null') {
          return null
        }
        if (isNaN(+match[1])) {
          throw Error('解析錯誤')
        }
        return Number(match[1])
      }
      new Error('解析錯誤')
    }
    // 解析數組值
    const parseArrValue = (context: { data: string }) => {
      const refMatch = /^({|\][ \n\t\r]*)/.exec(context.data)
      // 開啟新的狀態機
      if (refMatch) {
        return parseData(context)
      }
      const match = /^((".*?")|([0-9a-zA-Z]*))[ \n\t\r]*[,]?[ \n\t\r]*/.exec(context.data)
      if (match) {
        advance(context, match[0].length)
        const valMatch = /^"(.*?)"$/.exec(match[1])
        if (valMatch) {
          return valMatch[1]
        }
        if (match[1] === 'null') {
          return null
        }
        if (isNaN(+match[1])) {
          throw Error('解析錯誤')
        }
        return Number(match[1])
      }
      throw Error('解析錯誤')
    }

    在上面定義狀態的時候,解析對象、數組和數組值的時候只有開始狀態,而沒有結束狀態。只是結束狀態統一放入 isEnd 函數中。

    解析流程

    下面開始定義 parseData 函數:

    第一步

    const parseData = (ctx: { data: string }) => {
      let res: any = ''
      let currentState = State.INIT
      while (isEnd(ctx)) {
        switch (CurrentState) {
          case State.INIT:
            {
              const match = /^[ \t\n\r]*/.exec(ctx.data)
              if (match?.[0].length) {
                advance(ctx, match[0].length)
              }
              if (ctx.data[0] === '{') {
                res = {}
                currentState = State.OBJECTSTART
              } else if (ctx.data[0] === '[') {
                res = []
                currentState = State.ARRAYSTART
              } else {
                res = parseObjValue(ctx)
              }
            }
            break
          case State.OBJECTSTART:
            break
          case State.OBJVALSTART:
            break
          case State.OBJVALEND:
            break
          case State.ARRAYSTART:
            break
          case State.ARRVALSTART:
            break
          // no default
        }
      }
      return res
    }

    INIT 中,先去掉前面的空格、換行等字符,示例:

    const str1 = ' \t\n\r{"4":3,"s":"s","null":null,"arr":[1,"s",null],"obj":{}}'
    const str2 = '{"4":3,"s":"s","null":null,"arr":[1,"s",null],"obj":{}}'

    然后再判讀第一個字符是什么:

    • 如果是 {,則將狀態轉移到 OBJECTSTART,將 res 賦值一個空對象

    • 如果是 [,則將狀態轉移到 ARRAYSTART,將 res 賦值一個空數組

    • 如果都不是,則就是一個值,可以用對象解析屬性值的方法來解析,判讀是否是合法的字符串

    所以這里的狀態轉移到了對象解析 OBJECTSTART

    第二步

    const parseData = (ctx: { data: string }) => {
      let res: any = ''
      let currentState = State.INIT
      while (isEnd(ctx)) {
        switch (CurrentState) {
          case State.INIT:
            // 省略部分代碼
            break
          case State.OBJECTSTART:
            {
              const match = /^{[ \t\n\r]*/.exec(ctx.data)
              if (match) {
                advance(ctx, match[0].length)
                currentState = State.OBJVALSTART
              }
            }
            break
          case State.OBJVALSTART:
            break
          case State.OBJVALEND:
            break
          case State.ARRAYSTART:
            break
          case State.ARRVALSTART:
            break
          // no default
        }
      }
      return res
    }

    OBJECTSTART 中,消費掉 '{',將狀態轉移到 OBJVALSTART, 剩余字符數據:

    const str = '"4":3,"s":"s","null":null,"arr":[1,"s",null],"obj":{}}'

    第三步

    const parseData = (ctx: { data: string }) => {
      let res: any = ''
      let currentState = State.INIT
      while (isEnd(ctx)) {
        switch (CurrentState) {
          case State.INIT:
            // 省略部分代碼
            break
          case State.OBJECTSTART:
            // 省略部分代碼
            break
          case State.OBJVALSTART:
            {
              const match = /^"(.*?)"[ \n\t\r]*:[ \n\t\r]*/.exec(ctx.data)
              if (match) {
                advance(ctx, match[0].length)
                if (ctx.data[0] === '{' || ctx.data[0] === '[') {
                  res[match[1]] = parseData(ctx)
                } else {
                  res[match[1]] = parseObjValue(ctx)
                }
                currentState = State.OBJVALEND
              }
            }
            break
          case State.OBJVALEND:
            break
          case State.ARRAYSTART:
            break
          case State.ARRVALSTART:
            break
          // no default
        }
      }
      return res
    }

    先獲取 key: 等數組并消費,剩余字符數據:

    const str = '3,"s":"s","null":null,"arr":[1,"s",null],"obj":{}}'

    先判讀后續字符的第一個字符是什么:

    • 如果是 { 或者 [,則開啟一個新的狀態機

    • 否則直接用 parseObjValue 解析值

    最后將狀態轉移至 OBJVALEND

    第四步

    const parseData = (ctx: { data: string }) => {
      let res: any = ''
      let currentState = State.INIT
      while (isEnd(ctx)) {
        switch (CurrentState) {
          case State.INIT:
            // 省略部分代碼
            break
          case State.OBJECTSTART:
            // 省略部分代碼
            break
          case State.OBJVALSTART:
            // 省略部分代碼
            break
          case State.OBJVALEND:
            {
              const match = /^[ \t\n\r]*([,}\]])[ \t\n\r]*/.exec(ctx.data)
              if (match) {
                if (match[1] === ',') {
                  currentState = State.OBJVALSTART
                }
                advance(ctx, match[0].length)
              }
            }
            break
          case State.ARRAYSTART:
            break
          case State.ARRVALSTART:
            break
          // no default
        }
      }
      return res
    }

    如果后面匹配出來的字符是 ,,則表示后續還有其它的對象屬性,我們需要將狀態重新轉移到 OBJVALSTART, 如果是其它的 } 或者 ],則會在此次消費完畢,然后在 isEnd 中會退出狀態機。

    后續剩余字符的變化會依照上數狀態的變化而進行字符消費:

    const str = '3,"s":"s","null":null,"arr":[1,"s",null],"obj":{}}'
    // 1
    const str = ',"s":"s","null":null,"arr":[1,"s",null],"obj":{}}'
    // 2
    const str = '"s":"s","null":null,"arr":[1,"s",null],"obj":{}}'
    // 省略 s 和 null
    // 3 開啟新的狀態機
    const str = '[1,"s",null],"obj":{}}'
    // 4 結束狀態機
    const str = '],"obj":{}}'
    // 5 開啟新的狀態機
    const str = '{}}'
    // 6 結束狀態機
    const str = '}}'
    // 7 結束狀態機
    const str = '}'

    數組的處理

    const parseData = (ctx: { data: string }) =&gt; {
      let res: any = ''
      let currentState = State.INIT
      while (isEnd(ctx)) {
        switch (CurrentState) {
          case State.INIT:
            // 省略部分代碼
            break
          case State.OBJECTSTART:
            // 省略部分代碼
            break
          case State.OBJVALSTART:
            // 省略部分代碼
            break
          case State.OBJVALEND:
            // 省略部分代碼
            break
          case State.ARRAYSTART:
            {
              const match = /^\[[ \t\n\r]*/.exec(ctx.data)
              if (match) {
                advance(ctx, match[0].length)
                currentState = State.ARRVALSTART
              }
            }
            break
          case State.ARRVALSTART:
            res.push(parseArrValue(ctx))
            break
          // no default
        }
      }
      return res
    }

    如果第一個字符為 [,則會開啟新的狀態機,狀態也會轉換為 ARRAYSTART,然后在 ARRAYSTART 狀態內進行數組值的轉換。

    到這里整個 JSON.parse 的實現思路差不多,但是上述的流程應該有沒考慮到的地方,但是大體差不多,只是邊界的處理問題。測試示例:

    // 數據使用上面的 testJson
    const raws = JSON.stringify(testJson)
    const rawp = JSON.parse(raws)
    const cusp = parse(raws)
    console.log(raws, 'JSON.stringify')
    console.log(rawp, 'JSON.parse')
    console.log(cusp, 'parse')

    結果:

    怎么使用JSON?stringify及parse方法實現數據深拷貝

    完整代碼

    const State = {
      INIT: 'INIT',
      OBJECTSTART: 'OBJECTSTART',
      ARRAYSTART: 'ARRAYSTART',
      OBJVALSTART: 'OBJVALSTART',
      OBJVALEND: 'OBJVALEND',
      ARRVALSTART: 'ARRVALSTART'
    }
    const isEnd = (ctx: { data: string }, res: any) => {
      if (!ctx.data) {
        return false
      }
      const match = /^(}|\])[ \t\n\r]*/.exec(ctx.data)
      if (match) {
        if (
          match[1] === '}' && getType(res) !== 'Object' ||
          match[1] === ']' && getType(res) !== 'Array'
        ) {
          throw Error('解析錯誤')
        }
        advance(ctx, match[0].length)
        return false
      }
      return true
    }
    const advance = (context: { data: string }, num: number) => {
      context.data = context.data.slice(num)
    }
    const parseObjValue = (context: { data: string }) => {
      const match = /^[ \n\t\r]*((".*?")|([0-9A-Za-z]*))[ \t\n\r]?/.exec(context.data)
      if (match) {
        advance(context, match[0].length)
        const valMatch = /^"(.*?)"$/.exec(match[1])
        if (valMatch) {
          return valMatch[1]
        }
        if (match[1] === 'null') {
          return null
        }
        if (isNaN(+match[1])) {
          throw Error('解析錯誤')
        }
        return Number(match[1])
      }
      new Error('解析錯誤')
    }
    const parseArrValue = (context: { data: string }) => {
      const refMatch = /^({|\][ \n\t\r]*)/.exec(context.data)
      if (refMatch) {
        return parseData(context)
      }
      const match = /^((".*?")|([0-9a-zA-Z]*))[ \n\t\r]*[,]?[ \n\t\r]*/.exec(context.data)
      if (match) {
        advance(context, match[0].length)
        const valMatch = /^"(.*?)"$/.exec(match[1])
        if (valMatch) {
          return valMatch[1]
        }
        if (match[1] === 'null') {
          return null
        }
        if (isNaN(+match[1])) {
          throw Error('解析錯誤')
        }
        return Number(match[1])
      }
      throw Error('解析錯誤')
    }
    const parseData = (ctx: { data: string }) => {
      let res: any = ''
      let currentState = State.INIT
      while (isEnd(ctx, res)) {
        switch (currentState) {
          case State.INIT:
            {
              const match = /^[ \t\n\r]*/.exec(ctx.data)
              if (match?.[0].length) {
                advance(ctx, match[0].length)
              }
              if (ctx.data[0] === '{') {
                res = {}
                currentState = State.OBJECTSTART
              } else if (ctx.data[0] === '[') {
                res = []
                currentState = State.ARRAYSTART
              } else {
                res = parseObjValue(ctx)
              }
            }
            break
          case State.OBJECTSTART:
            {
              const match = /^{[ \t\n\r]*/.exec(ctx.data)
              if (match) {
                advance(ctx, match[0].length)
                currentState = State.OBJVALSTART
              }
            }
            break
          case State.OBJVALSTART:
            {
              const match = /^"(.*?)"[ \n\t\r]*:[ \n\t\r]*/.exec(ctx.data)
              if (match) {
                advance(ctx, match[0].length)
                if (ctx.data[0] === '{' || ctx.data[0] === '[') {
                  res[match[1]] = parseData(ctx)
                } else {
                  res[match[1]] = parseObjValue(ctx)
                }
                currentState = State.OBJVALEND
              }
            }
            break
          case State.OBJVALEND:
            {
              const match = /^[ \t\n\r]*([,}\]])[ \t\n\r]*/.exec(ctx.data)
              if (match) {
                if (match[1] === ',') {
                  currentState = State.OBJVALSTART
                }
                advance(ctx, match[0].length)
              }
            }
            break
          case State.ARRAYSTART:
            {
              const match = /^\[[ \t\n\r]*/.exec(ctx.data)
              if (match) {
                advance(ctx, match[0].length)
                currentState = State.ARRVALSTART
              }
            }
            break
          case State.ARRVALSTART:
            res.push(parseArrValue(ctx))
            break
          // no default
        }
      }
      return res
    }
    export const parse = (data: string | number | null) => {
      if (typeof data === 'number' || data === null) {
        return data
      }
      const context = { data }
      return parseData(context)
    }

    以上就是關于“怎么使用JSON stringify及parse方法實現數據深拷貝”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

    向AI問一下細節

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

    AI

    烟台市| 大竹县| 正定县| 磐石市| 土默特左旗| 屯留县| 山阳县| 湖南省| 恭城| 于都县| 临洮县| 安远县| 礼泉县| 卢湾区| 全南县| 自贡市| 钦州市| 田林县| 嘉黎县| 乌鲁木齐市| 南京市| 敦化市| 衡阳市| 通许县| 株洲县| 长宁区| 咸阳市| 丰都县| 大丰市| 宽甸| 广安市| 黑龙江省| 霸州市| 昭觉县| 平定县| 治多县| 泰宁县| 临城县| 内黄县| 修文县| 怀安县|