经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » JS/JS库/框架 » JavaScript » 查看文章
使用js实现复制功能
来源:jb51  时间:2022/8/23 11:26:34  对本文有异议

本文实例为大家分享了使用js实现复制功能的具体代码,供大家参考,具体内容如下

复制

1.遍历复制(for in)

特征:不修改引用关系(原来的属性还在),仅能复制字符属性,Symbol不能复制,不可枚举属性不能复制,原型链不能复制。浅复制

2.JOSN.parse(JSON.stringify(obj)) 转换复制

特征:修改引用关系(相当于创建一个新的对象,不再拥有原来的属性),仅能复制字符属性,Symbol不能复制,不可枚举属性不能复制,原型链不能复制,函数和其他类型不能复制。深复制

3.{…obj}解构赋值复制

特征:修改引用关系,Symbol和函数都能复制,不可枚举属性和原型链都不能复制。浅复制

4.Object.assign()对象复制

特征:不修改引用关系,可以复制属性、方法、Symbol类型,不可枚举属性和原型链都不能复制。浅复制

深复制**

1.使用defineProperty***

  1. function cloneObject(source,target){
  2. ? ? if(source === null||source === undefined) return source;
  3. ? ? if(source===document) return;
  4. ? ? //判断target是不是继承对象的实例,是不是引用类型(null,undefined,Boolean,string,number都不是引用类型)
  5. ? ? if(!Object.prototype.isPrototypeOf(target)){
  6. ? ? ? ? //判断源对象是不是dom元素
  7. ? ? ? ? if(HTMLElement.prototype.isPrototypeOf(source)){
  8. ? ? ? ? ? ? //创建dom元素
  9. ? ? ? ? ? ? ?target = document.createElement(source.nodeName);
  10. ? ? ? ? }else if(source.constructor === RegExp){
  11. ? ? ? ? ? ? // 任何正则表达式都有source和flags,source是正则内容,flags是正则修饰符
  12. ? ? ? ? ? ? // 因为这两个属性都是只读属性,不能写入,必须通过构造函数创建时带入
  13. ? ? ? ? ? ? target = new RegExp(source.source,source.flags);
  14. ? ? ? ? }else if(source.constructor === Date){
  15. ? ? ? ? ? ? // 日期对象在创建的对象中将原有的日期对象放入,可以让当前日期对象变为原有日期对象的值,但是没有引用关系
  16. ? ? ? ? ? ? targer = new Date(source);
  17. ? ? ? ? }else if(source.constructor === Function){
  18. ? ? ? ? ? ? // 复制函数,通过正则表达式将函数中的参数以及函数体内容提取到数组中,然后通过new Function()创建
  19. ? ? ? ? ? ? var arr = source.toString().replace(/\n|\r/g,"").trim().match(/\((.*?)\)\s*\{(.*)\}/).slice(1);
  20. ? ? ? ? ? ? target = new Function(arr[0].trim(),arr[1]);
  21. ? ? ? ? }else if(source.constructor === Set){
  22. ? ? ? ? ? ? // set类型,在处理时,new Set时可以带入数组,因此我们将原有set的列表强转为数组,并且将这个强转后的数组复制给新数组
  23. ? ? ? ? ? ? target = new Set(cloneObject(Array.from(source.values())));
  24. ? ? ? ? }else if(source.constructor === Map){
  25. ? ? ? ? ? ? target = new Map();
  26. ? ? ? ? ? ? // 如果是map类型,遍历map中每个元素
  27. ? ? ? ? ? ? for(var [key,value] of source.entries()){
  28. ? ? ? ? ? ? ? ? // 如果key是引用类型,
  29. ? ? ? ? ? ? ? ? if(Object.prototype.isPrototypeOf(key)){
  30. ? ? ? ? ? ? ? ? ? ? ?// 如果value引用类型,则将key和value分别做复制,并且将返回的结果放在map中
  31. ? ? ? ? ? ? ? ? ? ? if(Object.prototype.isPrototypeOf(value)){
  32. ? ? ? ? ? ? ? ? ? ? ? ? target.set(cloneObject(key),cloneObject(value));
  33. ? ? ? ? ? ? ? ? ? ? }else{
  34. ? ? ? ? ? ? ? ? ? ? ? ? ?//如果value不是引用类型,只将key复制,并且放入map
  35. ? ? ? ? ? ? ? ? ? ? ? ? target.set(cloneObject(key),value);
  36. ? ? ? ? ? ? ? ? ? ? }
  37. ? ? ? ? ? ? ? ? }else{
  38. ? ? ? ? ? ? ? ? ? ? // 这是key不是引用类型时
  39. ? ? ? ? ? ? ? ? ? ? if(Object.prototype.isPrototyeOf(value)){
  40. ? ? ? ? ? ? ? ? ? ? ? ? target.set(key,cloneObject(value));
  41. ? ? ? ? ? ? ? ? ? ? }else{
  42. ? ? ? ? ? ? ? ? ? ? ? ? target.set(key,value);
  43. ? ? ? ? ? ? ? ? ? ? }
  44. ? ? ? ? ? ? ? ? }
  45. ? ? ? ? ? ? }
  46. ? ? ? ? }
  47. ? ? ? ? else{
  48. ? ? ? ? //除了null和undefined,其他类型都有constructor。任何对象的constructor都是它的类型,利用其constructor创建对象
  49. ? ? ? ? //通过对象类型的反射创建新的同类型对象
  50. ? ? ? ? ? ? target = new source.constructor();
  51. ? ? ? ? }
  52. ? ? ? ??
  53. ? ? }
  54. ? ? //获取对象的所有字符属性名和Symbol属性名的数组
  55. ? ? var names = Object.getOwnPropertyName(source).concat(Object.getOwnPropertySymbols(source));
  56. ? ? for(var i = 0;i < names.lenght; i++){
  57. ? ? ? ? // 如果当前复制的是函数,并且这个函数的属性是prototype,那么这个属性不复制,否则会死循环
  58. ? ? ? ? if(source.constructor === Function&&names[i] === "prototype")
  59. ? ? ? ? ? ? continue;
  60. ? ? ? ? // 获取当前属性名的描述对象
  61. ? ? ? ? var desc = Object.getOwnPropertyDescriptor(source,names[i]);
  62. ? ? ? ? // ? 这个描述对象的值如果是引用类型
  63. ? ? ? ? if(Object.prototype.isPrototypeOf(desc.value)){
  64. ? ? ? ? ? ? ?// 根据需要将源对象的描述内容设置给当前目标对象相同属性名的描述内容,及值付为刚才创建相同类型的对象
  65. ? ? ? ? ? ? Object.defineProperty(target,names[i],{
  66. ? ? ? ? ? ? ? ? enumerable:desc.enumerable,
  67. ? ? ? ? ? ? ? ? configurable:desc.configurable,
  68. ? ? ? ? ? ? ? ? writable:desc.writable,
  69. ? ? ? ? ? ? ? ? value:cloneObject(desc.value)
  70. ? ? ? ? ? ? });
  71. ? ? ? ? }else{
  72. ? ? ? ? ? ? ?//如果描述的对象的值不是引用类型,直接将描述对象设置给目标对象的这个属性
  73. ? ? ? ? ? ? Object.defineProperty(target,names.desc);
  74. ? ? ? ? }
  75. ? ? }
  76. ? ? return target;
  77. }
  78.  
  79.  
  80. //原型.isPrototypeOf(对象)。对象里面是不是拥有xx的原型
  81. //反射:通过对象

2.使用JSON对象实现深复制

使用**JSON.parse(str)**可以将字符串转换成对象;

使用**JSON.stringify(obj)**将对象转换成对象形式的字符串,其中无法转换对象中的方法,可以考虑先将对象中的方法使用toString()转为字符串,然后再转换使用JSON.stringify(obj);

*使用**JSON.parse(str)**可以将字符串转换成对象

  1. var obj={
  2. ? ? a:1,
  3. ? ? b:3,?? ?//ab复制不会随其中一个的变化而变化
  4. ? ? c:{?? ??? ?//c复制会随其中一个的变化而变化,因为c属于对象的地址引用关系
  5. ? ? ? ? d:10,
  6. ? ? ? ? e:20
  7. ? ? }
  8. };
  9. var o1 = JSON.parse(JSON.stringify(obj)); //将obj复制给o1

3.使用递归实现深复制

结构仅限于对象。如果存在数组、正则、日期对象、dom对象则不能使用。

  1. var obj = {
  2. a:1,
  3. b:2,
  4. c:{
  5. ?? ??? ?a:1,
  6. ? b:2,
  7. ? c:{
  8. ?? ??? ??? ?a:1,
  9. ? ? ? b:2,
  10. ? ? ? }
  11. }
  12. }
  13. //函数定义参数时,注意必要参数写在前面,非必要参数写在后面
  14. function cloneObj(source,target){
  15. ?? ?if(target === undefined) target = {};
  16. for(var prop in source){
  17. ? //如果
  18. ?? ??? ?if(typeof source[prop] === "object" && source[prop] != null){
  19. ? ? ? target[prop] = {};
  20. ? ? ? cloneObj(source[prop],target[prop]);
  21. ? }else{
  22. ?? ??? ??? ?target[prop] = source[prop];
  23. ? }
  24. }
  25. return target;
  26. }

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持w3xue。

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

本站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号