泸州网站建设唐网互联,青岛市区商场黄页,唐山哪里建轻轨和地铁,做外贸铝材哪个网站比较好谨慎使用JSON.stringify
为了避免因为对象是引用类型而造成的数据源污染#xff0c;我们通常使用 JSON.stringify 将其转换为字符串#xff0c;而后通过JSON.parse方法将字符串转化一个新对象来实现深拷贝。但是在这个过程中也会存在一些问题#xff0c;本文就介绍一下使用…谨慎使用JSON.stringify
为了避免因为对象是引用类型而造成的数据源污染我们通常使用 JSON.stringify 将其转换为字符串而后通过JSON.parse方法将字符串转化一个新对象来实现深拷贝。但是在这个过程中也会存在一些问题本文就介绍一下使用JSON.stringify可能遇到的一些问题尽可能在以后避免这些问题。
先看一段代码
let obj {name: leo,age: Infinity
}
let originObj JSON.stringify(obj)
console.log(originObj) // {name:leo,age:null}可以看到在转换过程中Infinity变成了null。
先看看解决办法
简单粗暴重新赋值age属性使用JSON.stringify的第二个参数
function censor(key, value) {if (value Infinity) {return Infinity;}return value;
}
const b JSON.stringify(obj, censor);const c JSON.parse(b,function (key, value) {return value Infinity ? Infinity : value;}
);
console.log(c); // {name: leo, age: Infinity}作为参考大家可能直接用了第一种方法。但是这里可以看到JSON.stringify其实还有第二个参数那么它有什么用呢接下来我们就来揭开它的神秘面纱。 JSON.stringify 的基本语法
语法
JSON.stringify(value[, replacer [, space]])JSON.stringify() 方法将 JavaScript 对象或值转换为 JSON 字符串如果指定了替换函数则可选择替换值如果指定了替换数组则可选择仅包含指定的属性。 简单来说JSON.stringify() 将一个值转换为相应的 JSON 格式的字符串。
参数替换器
也就是第二个参数replacer,该参数是可选的可以是函数或数组。
当是函数时在序列化过程中每个待序列化的属性都会被函数进行转换处理。
let replacerFun function (key, value) {console.log(key, value)if (key name) {return undefined}return value
}let myIntro {name: leo,age: 25,like: FE
}console.log(JSON.stringify(myIntro, replacerFun))
// {age:25,like:FE}这实际上是一个过滤函数它利用了JSON.stringify中的特性如果对象属性值未定义则在序列化时会被忽略稍后我们会提到。
在开始时replacer 函数将传递一个空字符串作为键值代表要字符串化的对象。
上面console.log(key, value)输出的值如下
{name: leo, age: 25, like: FE} // 其实是 {name: leo, age: 25, like: FE}, 不过是个空字符
ame leo
age 25
like FE
{age:25,like:FE}可见通过第二个参数我们可以更加灵活地操作和修改序列化目标的值。
当第二个参数是数组时只会序列化数组中包含的属性名称
JSON.stringify (myIntro, [ name ]) // {name:leo}第三个参数
指定一个空字符串进行缩进更常见的是指定一个数字代表几个空格。
console.log(JSON.stringify(myIntro))
console.log(JSON.stringify(myIntro, null, 2))// 输出
// {name:leo,age:25,like:FE}
// {
// name: leo,
// age: 25,
// like: FE
// }JSON.stringify使用场景
判断对象/数组值是否相等
let a [1,2,3],b [1,2,3];
JSON.stringify(a) JSON.stringify(b);// truelocalStorage/sessionStorage 存储对象
我们知道localStorage/sessionStorage只能存储字符串。当我们要存储对象时需要使用 JSON.stringify 将其转换为字符串然后在获取对象时使用 JSON.parse解析出来。
function setLocalStorage(key,val) {window.localStorage.setItem(key, JSON.stringify(val));
};function getLocalStorage(key) {let val JSON.parse(window.localStorage.getItem(key));return val;
};实现对象深拷贝
let myIntro {name: leo,age: 25,like: FE
}function deepClone() {return JSON.parse(JSON.stringify(myIntro))
}let copyMe deepClone(myIntro)
copyMe.like js only
console.log(myIntro, copyMe)// { name: leo, age: 25, like: FE } { name: leo, age: 25, like: js only }路由浏览器地址参数传递
由于浏览器参数只能通过字符串传递所以还需要JSON.stringify。
使用 JSON.stringify 的注意事项
在某些场景下使用 JSON.stringify 可能会引发一些难以发现的问题
转换属性值中有toJSON方法
如果转换值中有toJSON方法则该方法返回的值将是最终的序列化结果。
let toJsonMyIntro {name: Gopal,age: 25,like: FE,toJSON: function () {return frontend;},
};console.log(JSON.stringify(toJsonMyIntro)); // frontend转换后的值中有未定义、任意函数、符号值
分为两种情况
一种是数组对象未定义的、任意函数和符号值都会被转换为null。
JSON.stringify([undefined, Object, Symbol()]);
// [null,null,null]一种是非数组对象序列化时会被忽略。
JSON.stringify({ x: undefined, y: Object, z: Symbol() });
// {}对于这些情况我们可以使用JSON.stringify的第二个参数来使其满足我们的期望。
const testObj { x: undefined, y: Object, z: Symbol(test) }const resut JSON.stringify(testObj, function (key, value) {if (value undefined) {return undefined} else if (typeof value symbol || typeof value function) {return value.toString()}return value
})console.log(resut)
// {x:undefined,y:function Object() { [native code] },z:Symbol(test)}含有循环引用的对象
let objA {name: leo,
}let objB {age: 25,
}objA.age objB
objB.name objA
JSON.stringify(objA)上面的代码会报错 VM1140:11 Uncaught TypeError: Converting circular structure to JSON
以symbol为属性键的属性
所有使用符号作为键控的属性都将被完全忽略即使它们必须包含在替换参数中。
JSON.stringify({ [Symbol.for(foo)]: foo }, [Symbol.for(foo)])
// {}JSON.stringify({ [Symbol.for(foo)]: foo }, function (k, v) {if (typeof k symbol) {return a symbol;}
})
// undefined值为NaN和Infinity
数组值或具有 NaN 和 Infinity 值的非数组对象属性将转换为 null
let me {name: leo,age: Infinity,money: NaN,
};
let originObj JSON.stringify(me);
console.log(originObj); // {name:leo,age:null,money:null}JSON.stringify([NaN, Infinity])
// [null,null]具有不可枚举的属性值
默认情况下不可枚举属性被忽略。
let person Object.create(null, {name: { value: leo, enumerable: false },age: { value: 25, enumerable: true },
})console.log(JSON.stringify(person))
// {age:25}