当前位置: 首页 > news >正文

谨慎使用JSON.stringify

谨慎使用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

先看看解决办法:

  1. 简单粗暴,重新赋值age属性
  2. 使用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);// true

localStorage/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

数组值或具有 NaNInfinity 值的非数组对象属性将转换为 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"}

相关文章:

谨慎使用JSON.stringify

谨慎使用JSON.stringify 为了避免因为对象是引用类型而造成的数据源污染,我们通常使用 JSON.stringify 将其转换为字符串,而后通过JSON.parse方法将字符串转化一个新对象来实现深拷贝。但是在这个过程中也会存在一些问题,本文就介绍一下使用…...

驱动开发day8

编写LED灯的驱动&#xff0c;使用GPIO子系统&#xff0c;里面添加按键的中断处理 1.应用程序发送指令控制LED亮灭 2.按键1 按下&#xff0c;led1电位反转 按键2按下&#xff0c;led2电位反转 按键3 按下&#xff0c;led3电位反转 驱动程序 #include <linux/init.h> #i…...

CAS 机制

问题分析与思考&#xff1a; CAS 是 Java 中 Unsafe 类里面的方法&#xff0c;它的全称是 CompareAndSwap&#xff0c;比较并交换 的意思。 它的主要功能是能够保证在多线程环境下&#xff0c;对于共享变量的修改的原子性。 举个例子&#xff0c;比如说有这样一个场景&#xff…...

#P1003. [NOIP2009普及组] 道路游戏

题目描述 小新正在玩一个简单的电脑游戏。 游戏中有一条环形马路&#xff0c;马路上有 nn 个机器人工厂&#xff0c;两个相邻机器人工厂之间由一小段马路连接。小新以某个机器人工厂为起点&#xff0c;按顺时针顺序依次将这 nn 个机器人工厂编号为 1\sim n1∼n&#xff0c;因…...

python-网络爬虫.regular

regular 正则表达式 (regular expression) 正则表达式(regular expression)描述了一种字符串匹配的模式 &#xff08;pattern&#xff09;&#xff0c; 可以用来检查一个串是否含有某种子串、将匹配的子串替换或者从某个串 中取出符合某个条件的子串等。 正则表达式是由普通…...

手动搭建gateway,项目集成gateway实现Token效果

目录 背景步骤1、首先创建springboot项目2、引入依赖3、配置文件&#xff01;&#xff01;&#xff01;&#xff01;&#xff01;&#xff08;超级重要&#xff01;&#xff01;&#xff01;根据自己的需要进行配置&#xff09;4、相关类我们在服务中进行的白名单中接口的操作如…...

linux下SVN服务器搭建

在本教程中&#xff0c;我们将介绍如何在Linux系统下搭建Subversion&#xff08;SVN&#xff09;服务器。Subversion是一种流行的版本控制系统&#xff0c;它允许多个人在同一项目上进行协作&#xff0c;同时避免了他们各自的更改发生冲突。 安装SVN 在大多数Linux发行版中&am…...

技术等级 TRL 定义

“不同环境、不同目标下TRL表述不一样” 技术等级 TRL 定义 TRL1 基本原理提出和发现 TRL2 技术应用研究 TRL3 完成概念验证&#xff0c;如叶栅试验、燃烧室头部试验等 TRL4 完成模拟部件试验&#xff0e;如压气机性能试验&#xff0c;燃烧室扇形试验 TRL5 完…...

DHorse v1.3.0 发布,基于k8s的发布平台

综述 DHorse是一个简单易用、以应用为中心的云原生DevOps系统&#xff0c;具有持续集成、持续部署、微服务治理等功能&#xff0c;无需安装依赖Docker、Maven、Node等环境即可发布Java、Vue、React应用&#xff0c;主要特点&#xff1a;部署简单、操作简洁、功能快速。 新增特…...

Redis - 缓存的双写一致性

概念&#xff1a; 当修改了数据库的数据也要同时更新缓存的数据&#xff0c;缓存和数据库的数据要保持一致 那为什么会有不一致的情况呢&#xff1f; 如果不追求一致性&#xff0c;正常有两种做法 先修改数据库 后删除旧的缓存先删除旧的缓存 再修改数据库 我们以先删除旧的…...

opencv03-Mat矩阵API的使用

opencv03-Mat矩阵API的使用 构造方法(具体介绍看API文档) int main() {Mat m1 Mat(200, 100, CV_8UC1);imshow("o1", m1);Mat m2 Mat(Size(100, 200), CV_8UC1);imshow("o2", m2);Mat m3 Mat(200, 100, CV_8UC3, Scalar(255, 0, 0));imshow("o3&…...

2023届浙江大学MPA提面A资格经验总结分享

本人是去年报考的浙大MPA项目&#xff0c;并通过提面获得了A资格&#xff0c;新一年浙大MPA项目提前批面试已经开始了&#xff0c;受达立易考周老师邀请来分享下我的提面经验&#xff0c;希望我的经验能对还在迷茫中的小伙伴有所帮助。 点开提面通知&#xff0c;首先看到…...

BugKu CTF(杂项篇MISC)—想要种子吗

BugKu CTF(杂项篇MISC)—想要种子吗 提 示: 描 述:flag{} 题目下载后是一张图片&#xff0c;打开如下。 一、工具 十六进制编辑器010 editor kali系统文件分离工具binwalk或者foremost 维吉尼亚密码 STEGHIDE图片隐写工具 文章所需的软件下载地址 ARCHPR压缩包密码破解…...

类之间的关系

1、类关系 继承、实现、依赖、组合、聚合 继承&#xff1a;一个类继承另一个类&#xff1b; 实现&#xff1a;一个类实现另一个接口&#xff1b; 依赖&#xff1a;一个类作为另一个的局部变量&#xff0c;方法的参数&#xff0c;临时对象等&#xff1b; 组合&#xff1a;一个类…...

【蓝图】p40-p43对象引用、变量有效性、实现键盘控制物体自转、简单点名系统

p40-p43对象引用、变量有效性、实现键盘控制物体自转、简单点名系统 p40对象引用、变量有效性p41实现键盘控制物体自转创建bool值控制旋转实现通过键盘控制自转 p42p43简单点名系统Get All Actors Of Class&#xff08;获得场景中所有该类的actor演员&#xff09;getFor Each L…...

vscode设置远程登录和免密登录

首先&#xff0c;我们去官网下载VScode 安装过程比较简单&#xff0c;大家自行安装即可&#xff0c;注意建议安装在除C盘外的其他盘中。 安装完成后&#xff0c;打开我们下载好的VScode&#xff0c;点击左侧的Extensions选项&#xff0c;搜索Remote&#xff0c;Install第一项R…...

今日头条面试真题及答案,软件测试工程师面试秘籍

试题1&#xff0e;在浏览器地址栏里输入一个网址&#xff0c;接下来会发生什么&#xff1f; 答案&#xff1a;发生的操作如下。 &#xff08;1&#xff09;浏览器查找该网址的IP地址。 &#xff08;2&#xff09;浏览器根据解析得到的IP地址向Web服务器发送一个HTTP请求。 &am…...

JavaScript Windows 浏览器对象模型

Window 对象 BOM 的核心就是 window 对象所有浏览器都支持 window 对象。它表示浏览器窗口。所有 JavaScript 全局对象、函数以及变量均自动成为 window 对象的成员。全局变量是 window 对象的属性。全局函数是 window 对象的方法。HTML DOM 的 document 也是 window 对象的属…...

【uniapp 获取缓存及清除缓存】

小程序及H5 获取缓存&#xff1a; 使用uniapp中的wx.getStorageInfoSync()方法可以获取当前小程序或H5应用的本地缓存信息&#xff0c;如下所示&#xff1a; let storageInfo uni.getStorageInfoSync() console.log(storageInfo)其中&#xff0c;storageInfo是一个对象&…...

【vim 学习系列文章 2 - vim 常用插件配置】

文章目录 1.1 vim 常用插件1.1.1 vim 插件 Pathogen 管理1.1.2 vim 常用插件推荐1.1.3 vim Leaderf1.1.4 vim ripgrep 工具1.1.5 vim Leaderf 配合 rg1.1.6 vim autocmd 配置 1.2 其它类型文件 vimrc 配置1.2.1 System Verilog vimrc 配置 上篇文章&#xff1a;vim 学习系列文章…...

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする

日语学习-日语知识点小记-构建基础-JLPT-N4阶段(33):にする 1、前言(1)情况说明(2)工程师的信仰2、知识点(1) にする1,接续:名词+にする2,接续:疑问词+にする3,(A)は(B)にする。(2)復習:(1)复习句子(2)ために & ように(3)そう(4)にする3、…...

基于Flask实现的医疗保险欺诈识别监测模型

基于Flask实现的医疗保险欺诈识别监测模型 项目截图 项目简介 社会医疗保险是国家通过立法形式强制实施&#xff0c;由雇主和个人按一定比例缴纳保险费&#xff0c;建立社会医疗保险基金&#xff0c;支付雇员医疗费用的一种医疗保险制度&#xff0c; 它是促进社会文明和进步的…...

Linux相关概念和易错知识点(42)(TCP的连接管理、可靠性、面临复杂网络的处理)

目录 1.TCP的连接管理机制&#xff08;1&#xff09;三次握手①握手过程②对握手过程的理解 &#xff08;2&#xff09;四次挥手&#xff08;3&#xff09;握手和挥手的触发&#xff08;4&#xff09;状态切换①挥手过程中状态的切换②握手过程中状态的切换 2.TCP的可靠性&…...

最新SpringBoot+SpringCloud+Nacos微服务框架分享

文章目录 前言一、服务规划二、架构核心1.cloud的pom2.gateway的异常handler3.gateway的filter4、admin的pom5、admin的登录核心 三、code-helper分享总结 前言 最近有个活蛮赶的&#xff0c;根据Excel列的需求预估的工时直接打骨折&#xff0c;不要问我为什么&#xff0c;主要…...

React19源码系列之 事件插件系统

事件类别 事件类型 定义 文档 Event Event 接口表示在 EventTarget 上出现的事件。 Event - Web API | MDN UIEvent UIEvent 接口表示简单的用户界面事件。 UIEvent - Web API | MDN KeyboardEvent KeyboardEvent 对象描述了用户与键盘的交互。 KeyboardEvent - Web…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI

前一阵子在百度 AI 开发者大会上&#xff0c;看到基于小智 AI DIY 玩具的演示&#xff0c;感觉有点意思&#xff0c;想着自己也来试试。 如果只是想烧录现成的固件&#xff0c;乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外&#xff0c;还提供了基于网页版的 ESP LA…...

sqlserver 根据指定字符 解析拼接字符串

DECLARE LotNo NVARCHAR(50)A,B,C DECLARE xml XML ( SELECT <x> REPLACE(LotNo, ,, </x><x>) </x> ) DECLARE ErrorCode NVARCHAR(50) -- 提取 XML 中的值 SELECT value x.value(., VARCHAR(MAX))…...

智能分布式爬虫的数据处理流水线优化:基于深度强化学习的数据质量控制

在数字化浪潮席卷全球的今天&#xff0c;数据已成为企业和研究机构的核心资产。智能分布式爬虫作为高效的数据采集工具&#xff0c;在大规模数据获取中发挥着关键作用。然而&#xff0c;传统的数据处理流水线在面对复杂多变的网络环境和海量异构数据时&#xff0c;常出现数据质…...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

听写流程自动化实践,轻量级教育辅助

随着智能教育工具的发展&#xff0c;越来越多的传统学习方式正在被数字化、自动化所优化。听写作为语文、英语等学科中重要的基础训练形式&#xff0c;也迎来了更高效的解决方案。 这是一款轻量但功能强大的听写辅助工具。它是基于本地词库与可选在线语音引擎构建&#xff0c;…...