功能比json.stringify强大的stringify(亲测好用)(代码片段)

乔碧萝·乔斯达 乔碧萝·乔斯达     2023-02-01     633

关键词:

介绍

        写了一个能将对象或数组转换成字符串(内部能转义多种数据类型)的函数,供大家使用。

        原理是把值转化为js代码字符串,再利用eval()函数把字符串转化为对象或数组,实现深拷贝。

        使用场景:localStorage、sessionStorage存储及转换,各种局限于只能使用字符串存储或传递对象的场景。

例子:

    const obj = 
            a: NaN,
            b: '',
            c: true,
            d()
                console.log('d')
            ,
            e: async function*()
                consoel.log('e')
            ,
            f: class ,
            g: [],
            h: new Map([[, []]]),
            i: new Set([1,2,1,3]),
            j: /^j$/g,
            [Symbol('k')]: Symbol.for('k'),
            l: 18n,
            m: Math,
            n: new ArrayBuffer(9)
        

    const jsStr = stringify(obj)
    console.log(jsStr)
    /*
        (a: NaN,b: '',c: true,d: function d() 
                console.log('d')
            ,e: async function* () 
                consoel.log('e')
            ,f: class A ,g: [],h: new Map([[, []]]),i: new Set([1,2,3]),j: /^j$/g,l: 18n,m: Math,n: new ArrayBuffer(9),[Symbol('k')]: Symbol.for('k'))
    */

    console.log(eval(jsStr)) // 输出复制后的源对象

以下是源代码(源代码简单易读):

/**
 * 将数组或对象转化为字符串
 */
const typings = 
    number: '[object Number]',
    string: '[object String]',
    boolean: '[object Boolean]',
    symbol: '[object Symbol]',
    bigInt: '[object BigInt]',
    null: '[object Null]',
    undefined: '[object Undefined]',
    object: '[object Object]',
    array: '[object Array]',
    regExp: '[object RegExp]',
    math: '[object Math]',
    map: '[object Map]',
    set: '[object Set]',
    function: '[object Function]',
    generator: '[object GeneratorFunction]',
    async: '[object AsyncFunction]',
    asyncGenerator: '[object AsyncGeneratorFunction]',
    arrayBuffer: '[object ArrayBuffer]'


const classReg = /^class/
const arrowReg = /=\\>/
const funcReg = /^function/
const asyncFuncReg = /^async\\s+function/
const asyncGeneratorReg = /^async\\s+\\*function/

/**
 * 主函数
 * @param object | array val 
 * @returns string
 */
function stringify(val) 
    const type = getType(val)
    // 处理边界
    if (
        type !== typings.object &&
        type !== typings.array
    ) 
        throw new TypeError('Arguments are not arrays or objects')
    

    return '(' + handler(val, type) + ')'


/**
 * 处理器
 * @param any val 
 * @param string type 
 * @returns string
 */
function handler(val, type) 
    switch (type) 
        case typings.number:
            return createNum(val)
        case typings.string:
            return createStr(val)
        case typings.boolean:
            return createBool(val)
        case typings.null:
            return createNull()
        case typings.undefined:
            return createUndefined()
        case typings.bigInt:
            return createBigInt(val)
        case typings.symbol:
            return createSymbol(val)
        case typings.function:
            return createFunc(val)
        case typings.generator:
            return createGenerator(val)
        case typings.async:
            return createAsync(val)
        case typings.asyncGenerator:
            return createAsyncGenerator(val)
        case typings.object:
            return createObj(val)
        case typings.array:
            return createArr(val)
        case typings.map:
            return createMap(val)
        case typings.set:
            return createSet(val)
        case typings.regExp:
            return createRegExp(val)
        case typings.math:
            return createMath()
        case typings.arrayBuffer:
            return createBuffer(val)
        default:
            return
    


/**
 * 创建函数
 */
function createNum(num) 
    return num


function createStr(str) 
    return `'$str'`


function createBool(bool) 
    return bool ? 'true' : 'false'


function createNull() 
    return 'null'


function createUndefined() 
    return 'undefined'


function createBigInt(bigInt) 
    return bigInt.toString() + 'n'


function createSymbol(symbol) 
    const description = symbol.description
    const isFor = Symbol.for(description) === symbol

    function isVoid(val) 
        return val === undefined || val === ''
    
    return isFor ? `Symbol.for($isVoid(description) ? '' : `'$description'`)` : `Symbol($isVoid(description) ? '' : `'$description'`)`


function createFunc(func) 
    const funcStr = func.toString()

    if (funcReg.test(funcStr) || arrowReg.test(funcStr) || classReg.test(funcStr)) 
        return funcStr
     else 
        return `function $funcStr`
    


function createGenerator(generator) 
    const generatorStr = generator.toString()

    return funcReg.test(generatorStr) ? generatorStr : `function $generatorStr`


function createAsync(asyncFunc) 
    const asyncFuncStr = asyncFunc.toString()

    if (asyncFuncReg.test(asyncFuncStr) || arrowReg.test(asyncFuncStr)) 
        return asyncFuncStr
     else 
        return asyncFuncStr.replace('async ', 'async function ')
    


function createAsyncGenerator(asyncGenerator) 
    const asyncGeneratorStr = asyncGenerator.toString()

    return asyncGeneratorReg.test(asyncGeneratorStr) ? asyncGeneratorStr : asyncGeneratorStr.replace('async *', 'async function*')


function createObj(obj) 
    let start = ''
    let end = ''
    let res = ''

    for (const key in obj) 
        if (obj.hasOwnProperty(key)) 
            res += `$key: $handler(obj[key], getType(obj[key])),`
        
    
    const symbolList = Object.getOwnPropertySymbols(obj)
    for (const symbol of symbolList) 
        const symbolStr = createSymbol(symbol)
        res += `[$symbolStr]: $handler(obj[symbol], getType(obj[symbol])),`
    

    return start + res.slice(0, -1) + end


function createArr(arr) 
    let start = '['
    let end = ']'
    let res = ''

    for (const item of arr) 
        res += handler(item, getType(item)) + ','
    

    return start + res.slice(0, -1) + end


function createMap(map) 
    let start = 'new Map(['
    let end = '])'
    let res = ''
    map.forEach((val, key) => 
        res += `[$handler(key, getType(key)), $handler(val, getType(val))],`
    )

    return start + res.slice(0, -1) + end


function createSet(set) 
    let start = 'new Set('
    let end = ')'

    return start + createArr([...set]) + end


function createRegExp(regExp) 
    return regExp


function createMath() 
    return 'Math'


function createBuffer(arrayBuffer) 
    return `new ArrayBuffer($arrayBuffer.byteLength)`


/**
 * 封装Object.toString方法
 * @param any val 
 * @returns string
 */
function getType(val) 
    return Object.prototype.toString.call(val)

qs.stringify、qs.parse、json.stringify的使用和区别

...安装,是一个npm仓库所管理的包。importqsfrom'qs'而qs.stringify()将对象序列化成URL的形式,以&进行拼接。如图qs.parse()将URL解析成对象的形式JSON是正常类型的JSON JSON.stringify同qs.stringify()对比,功能虽然是都是序列化,但是... 查看详情

敏捷bi比传统bi功能强大是否属实?

关于大数据的资讯铺天盖地而来,让人眼花缭乱。虽然资讯很精彩,我们也看到了大数据背后的价值,很多企业选择了商业智能BI产品。商业智能在使用上可分为敏捷BI与传统BI,从名字来看敏捷BI要比传统BI显得利索强大,事实... 查看详情

json序列化

...加双引号。JSON是ECMAScript5定义的对象,有两个方法:SON.stringify()和JSON.parse()。功能:把JavaScript对象序列化为JSON字符串(JavaScript对象(Object)转换成JSON数据传输)语法:JSON.stringify(value[,replacer[,space]])=>JSON.stringify(value,replacer,space)功... 查看详情

json.parse()与json.stringify()的区别

JSON.parse()与JSON.stringify()的区别JSON.parse()【从一个字符串中解析出json对象】例子://定义一个字符串vardata=‘{"name":"goatling"}‘//解析对象??JSON.parse(data)结果是:?name:"goatling"JSON.stringify()【从一个对象中解析出字符串】vardata={name:‘go... 查看详情

json.stringify()的深度使用

在使用JSON.stringify()对JSON数据进行序列化时1>如果里面的属性是function,则会被忽略constdata={a:‘a‘,fn:funciton(){returntrue}}JSON.stringify(data);//"{"a":"a"}"*******fn属性被忽略了**********2>如果里面的属性的值是undefined,也是会被忽略的constda 查看详情

json.parse()与json.stringify()的区别

...tling"}‘//解析对象??JSON.parse(data)结果是:?name:"goatling"JSON.stringify()【从一个对象中解析出字符串】vardata={name:‘goatling‘}JSON.stringify(data)结果是:‘{"nam 查看详情

小tips:qs.stringify()和json.stringify()的区别以及在vux中使用post提交表单数据需要qs库序列化

...列化。假设我要提交的数据如下vara={name:‘hehe‘,age:10};qs.stringify序列化结果如下name=hehe&age=10而JSON.stringify序列化结果如下:"{"a":"hehe","age":10}"vux中使用post提交表单数据:this.$htt 查看详情

JSON.stringify 的反转?

】JSON.stringify的反转?【英文标题】:ReverseofJSON.stringify?【发布时间】:2012-06-2516:05:12【问题描述】:我正在对像\'foo\':\'bar\'这样的对象进行字符串处理如何将字符串转回对象?【问题讨论】:请注意,foo:\'bar\'不是有效的JSON(... 查看详情

深浅拷贝(代码片段)

...。深拷贝原则上需要深度递归的方式解决或JSON.parse(JSON.stringify(object))。Object.assign 也为浅拷贝(真对2层以上),只不过比普通复制深一层。JSON.parse和JSON.stringifyJSON.parse:从一个字符串中解析出JSON对象。vardata=‘"name":"llpp"‘JSO... 查看详情

使用 JSON.stringify 时不需要的数组索引

】使用JSON.stringify时不需要的数组索引【英文标题】:UnwantedarrayindexeswhenusingJSON.stringify【发布时间】:2012-02-1109:04:27【问题描述】:我使用JSON.stringify方法将数组传递给服务器。我有一个包含4个元素的数组:arr[10]=1;arr[20]=1;arr[30]... 查看详情

带有缩进的 JSON.Stringify [重复]

】带有缩进的JSON.Stringify[重复]【英文标题】:JSON.Stringifywithintendation[duplicate]【发布时间】:2016-09-1800:29:53【问题描述】:如何格式化一个字符串化的json对象?JSON.stringify(a:\'avalue\',b:\'bvalue\');要输出这个:a:\'valuea\',b:\'valueb\'而... 查看详情

如何删除嵌套的 JSON.stringify() 属性

】如何删除嵌套的JSON.stringify()属性【英文标题】:HowtoremovenestedJSON.stringify()properties【发布时间】:2017-08-2618:05:38【问题描述】:我正在尝试使用Typescript修改字符串。该字符串由JSON.stringify()方法创建。我想删除"inputPort"的属性"id... 查看详情

json.parse和json.stringify的作用

...意:str每个属性名都必须是双引号,不然会报错;//JSON.stringify()将一个json对象转化成字符串格式v 查看详情

json.stringify方法

用过json的应该都知道,把一个对象通过 stringify 之后提交给后台或者存储在 Storage 里是很常用的手段。但是IE6-7下没有JSON对象,所以要借助 json2.js 来实现。今天我们来简单介绍下 stringify 方法的一... 查看详情

深度使用json.stringify()

按照JSON的规范,使用JSON.stringify()做对象序列化时,如果一个属性为函数,那这个属性就会被忽略。constdata1={a:‘aaa‘,fn:function(){returntrue}}JSON.stringify(data)//结果是"{"a":"aaa"}"还有一种情况,一个属性的值为undefinedconstdata2={a:‘abc‘,... 查看详情

angular.copy() 和 JSON.parse(JSON.stringify()) 之间的区别?

】angular.copy()和JSON.parse(JSON.stringify())之间的区别?【英文标题】:Differencesbetweenangular.copy()andJSON.parse(JSON.stringify())?【发布时间】:2015-06-2902:18:45【问题描述】:有人能解释一下angular.copy()和JSON.parse(JSON.stringify())之间的区别吗?... 查看详情

JSON.stringify() 数组的怪异与 Prototype.js

】JSON.stringify()数组的怪异与Prototype.js【英文标题】:JSON.stringify()arraybizarrenesswithPrototype.js【发布时间】:2012-11-2502:06:51【问题描述】:我正在尝试找出我的json序列化出了什么问题,将我的应用程序的当前版本与旧版本一起使用... 查看详情

你不知道的javascript中的5个json秘密功能

...以及我的系列文章。在开发中,我们会经常使用JSON.stringify(object)来序列化对象,但JSON.stringify方法 查看详情