视频1 视频21 视频41 视频61 视频文章1 视频文章21 视频文章41 视频文章61 推荐1 推荐3 推荐5 推荐7 推荐9 推荐11 推荐13 推荐15 推荐17 推荐19 推荐21 推荐23 推荐25 推荐27 推荐29 推荐31 推荐33 推荐35 推荐37 推荐39 推荐41 推荐43 推荐45 推荐47 推荐49 关键词1 关键词101 关键词201 关键词301 关键词401 关键词501 关键词601 关键词701 关键词801 关键词901 关键词1001 关键词1101 关键词1201 关键词1301 关键词1401 关键词1501 关键词1601 关键词1701 关键词1801 关键词1901 视频扩展1 视频扩展6 视频扩展11 视频扩展16 文章1 文章201 文章401 文章601 文章801 文章1001 资讯1 资讯501 资讯1001 资讯1501 标签1 标签501 标签1001 关键词1 关键词501 关键词1001 关键词1501 专题2001
详解关于JSON.parse()和JSON.stringify()的性能小测试
2020-11-27 22:00:02 责编:小采
文档


JSON.parse(JSON.stringify(obj))我们一般用来深拷贝,其过程说白了,就是利用 JSON.stringify 将js对象序列化(JSON字符串),再使用JSON.parse来反序列化(还原)js对象。至于这行代码为什么能实现深拷贝,以及它有什么局限性等等,不是本文要介绍的。本文要探究的是,这行代码的执行效率如何?如果随意使用会不会造成一些问题?

先上两个js性能测试的依赖函数

/**
 * 一个简单的断言函数
 * @param value {Boolean} 断言条件
 * @param desc {String} 一个消息
 */
function assert(value, desc) {
 let li = document.createElement('li');
 li.className = value ? 'pass' : 'fail';
 li.appendChild(document.createTextNode(desc));
 document.getElementById('results').appendChild(li);
}
/**
 * 一个测试套件,定时器是为了多次执行减少误差
 * @param fn {Function} 需要多次执行的代码块(需要测试、比对性能的代码块)
 * @param config {Object} 配置项,maxCount: 执行代码块的for循环次数,times: 定时器执行次数
 */
function intervalTest(fn, config = {}) {
 let maxCount = config.maxCount || 1000;
 let times = config.times || 10;
 let timeArr = [];
 let timer = setInterval(function () {
 let start = new Date().getTime();
 for (let i = 0; i < maxCount; i++) {
 fn.call(this);
 }
 let elapsed = new Date().getTime() - start;
 assert(true, 'Measured time: ' + elapsed + ' ms');
 timeArr.push(elapsed);
 if (timeArr.length === times) {
 clearInterval(timer);
 let average = timeArr.reduce((p, c) => p + c) / times;
 let p = document.createElement('p');
 p.innerHTML = `for循环:${maxCount}次,定时器执行:${times}次,平均值:${average} ms`;
 document.body.appendChild(p);
 }
 }, 1000);
}

定义一些初始数据

let jsonData = {
 title: 'hhhhh',
 dateArr: [],
 series: [
 {
 name: 'line1',
 data: []
 },
 {
 name: 'line2',
 data: []
 },
 {
 name: 'line3',
 data: []
 },
 ]
};

let res = [
 {
 name: 'line1',
 value: 1
 },
 {
 name: 'line2',
 value: 2
 },
 {
 name: 'line3',
 value: 3
 },
];

场景1:模拟真实环境中图表数据实时更新

数据处理函数

/**
 * 处理json数据的函数。模拟真实环境中图表数据实时更新
 * @param lastData {Object} 上一次的数据
 * @param res {Array} 当前数据
 * @returns data 处理完成后的结果集
 */
function handleJsonData(lastData, res) {
 // 1. 使用 JSON.parse(JSON.stringify()) 深拷贝
 let data = JSON.parse(JSON.stringify(lastData));

 // 2. 不使用JSON序列化,直接修改参数
 // let data = lastData;

 if (data.dateArr.length > 60) {
 data.dateArr.shift();
 for (let i = 0; i < data.series.length; i++) {
 data.series[i].data.shift();
 }
 }
 data.dateArr.push(new Date().toTimeString().substr(0, 8));
 for (let i = 0; i < data.series.length; i++) {
 data.series[i].data.push(res[i].value);
 }
 return data;
}

maxCount=100

跑起来,先让maxCount=100,for循环100次

let jsonTest = function () {
 jsonData = handleJsonData(jsonData, res);
};

intervalTest(jsonTest, {maxCount: 100});

1.使用 JSON.parse(JSON.stringify()) 深拷贝 的结果:

2.不使用JSON序列化,直接修改参数 的结果:

function handleJsonData(lastData, res) {
 // 1. 使用 JSON.parse(JSON.stringify()) 深拷贝
 // let data = JSON.parse(JSON.stringify(lastData));

 // 2. 不使用JSON序列化,直接修改参数
 let data = lastData;
 
 // ...
}

maxCount=1000

intervalTest(jsonTest, {maxCount: 1000});

1.使用 JSON.parse(JSON.stringify()) 深拷贝 的结果:

2.不使用JSON序列化,直接修改参数 的结果:

maxCount=10000

intervalTest(jsonTest, {maxCount: 10000});

1.使用 JSON.parse(JSON.stringify()) 深拷贝 的结果:

2.不使用JSON序列化,直接修改参数 的结果:

场景2:判断一个对象是否为空对象

// 1. 使用 JSON.stringify() 判断一个对象是否为空对象
let isEmptyObject1 = function () {
 if (JSON.stringify(jsonData) === '{}') {
 // do something
 }
};

// 2. 使用 Object.keys().length 判断一个对象是否为空对象
let isEmptyObject2 = function () {
 if (Object.keys(jsonData).length === 0) {
 // do something
 }
};

只是走了一下判断条件,if内部没有执行代码

maxCount=1000

1.使用 JSON.stringify() 判断一个对象是否为空对象 的结果:

intervalTest(isEmptyObject1, {maxCount: 1000});

2.使用 Object.keys().length 判断一个对象是否为空对象 的结果:

intervalTest(isEmptyObject2, {maxCount: 1000});

maxCount=10000

1.使用 JSON.stringify() 判断一个对象是否为空对象 的结果:

2.使用 Object.keys().length 判断一个对象是否为空对象 的结果:

maxCount=100000

1.使用 JSON.stringify() 判断一个对象是否为空对象 的结果:

2.使用 Object.keys().length 判断一个对象是否为空对象 的结果:

关于JSON.parse()和JSON.stringify()的测试先到此为止,变换参数、更改执行的代码块可能会有不同结果,以上结果仅供参考。

小结论:能不用JSON.parse()和JSON.stringify()就不用,采用替代方案且性能更优的。PS:特别是需要多次执行的代码块,特别是这个JSON数据比较庞大时

下载本文
显示全文
专题