经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
小tips:使用JSON.parse(JSON.stringify(object))实现深拷贝的局限及扩展
来源:cnblogs  作者:风雨后见彩虹  时间:2020/12/28 9:52:00  对本文有异议

使用JSON.parse(JSON.stringify(object))实现深拷贝局限

大部分情况我们都可以使用JSON.parse(JSON.stringify(object))来实现深拷贝,但该方法也有局限性,如下:

  • 会忽略 undefined
  • 会忽略 symbol
  • 不能序列化函数
  • 不能解决循环引用的对象

例如:

  1. let a = {
  2. age: undefined,
  3. sex: Symbol('male'),
  4. jobs: function() {},
  5. name: 'yck'
  6. }
  7. let b = JSON.parse(JSON.stringify(a))
  8. console.log(b) // {name: "yck"}

 借用 MessageChannel 实现深拷贝

MessageChannel API允许我们创建一个新的消息通道,并通过它的两个MessagePort属性发送数据。

  1. var channel = new MessageChannel();

这样就创建了一个管道。

实例属性:

  1. channel.port1
  2. channel.port2

获取实例的两个端口,注意的是,两个端口都是只读的。

简单来说,MessageChannel创建了一个通信的管道,这个管道有两个端口,每个端口都可以通过postMessage发送数据,而一个端口只要绑定了onmessage回调方法,就可以接收从另一个端口传过来的数据。

一个简单的例子:

  1. var channel = new MessageChannel();
  2. var port1 = channel.port1;
  3. var port2 = channel.port2;
  4. port1.onmessage = function(event) {
  5. console.log("port1收到来自port2的数据:" + event.data);
  6. }
  7. port2.onmessage = function(event) {
  8. console.log("port2收到来自port1的数据:" + event.data);
  9. }
  10. port1.postMessage("发送给port2");
  11. port2.postMessage("发送给port1");

而通过 postMessage() 方法传输的 message 参数是深拷贝的。

  1. function deepClone(val) {
  2. return new Promise((resolve,reject) => {
  3. const {port1,port2} = new MessageChannel();
  4. port2.onmessage = e => resolve(e.data);
  5. port1.postMessage(val);
  6. })
  7. }
  8. let obj = {
  9. age: undefined,
  10. name: 'yck',
  11. c: {
  12. d: true
  13. }
  14. }
  15. obj.c.e = obj.c; // 循环引用
  16.  
  17. // 注意该方法是异步
  18. async function test() {
  19. const clone = await deepClone(obj);
  20. console.log(clone) // {age: undefined, name: "yck", c: {…}}
  21. }
  22. test()

但这个深拷贝只能解决 undefined 和循环引用对象的问题,对于 Symbol 和 function 依然束手无策。

详细可参考:《MessageChannel 消息通道》

简易版的深拷贝

  1. var extendCopy = (function f(p,c){
  2. var c = c || {};
  3. for (var i in p) {
  4. if(typeof p[i] === 'object'){
  5. c[i] = (p[i] instanceof Array) ? [] : {};
  6. f(p[i],c[i]);
  7. }else{
  8.  c[i] = p[i];
  9. } 
  10. }
  11. return c;
  12. });

详细可参考:《小tips:JS之浅拷贝与深拷贝》

lodash 的深拷贝函数

语法:

  1. _.cloneDeep(value)

示例:

  1. var objects = [{ 'a': 1 }, { 'b': 2 }];
  2. var deep = _.cloneDeep(objects);
  3. console.log(deep[0] === objects[0]);
  4. // => false

地址:https://lodash.com/docs/4.17.15#cloneDeep

原文链接:http://www.cnblogs.com/moqiutao/p/14171405.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号