javascript的一切实例都是对象,只是对象之间稍有不同,分为原始类型和合成类型。原始类型对象指的是字符串(String)、数值(Number)、布尔值(Boolean),合成类型对象指的是数组(Array)、对象(Object)、函数(Function)。

既然对象分为这两类,他们之间的最大差别是复制克隆的差别。普通对象存储的是对象的实际数据,而引用对象存储的是对象的引用地址,而把对象的实际内容单独存放,因为引用对象通常比较庞大,这是数据开销和内存开销优化的手段。通常初学者很难理解这部分内容,就像对象的原型一样,也是同一个概念。对象的原型也是引用对象,把原型的方法和属性放在单独内存当中,而对象的原型链则指向这个内存地址。尽管这部分内容比较拗口复杂,那其中的原理都是一致的,目的也一致。

1、原始类型对象的克隆

1.1、字符串的克隆

  1. var x="1";
  2. var y=x;
  3. y="2";
  4. // "1"
  5. alert(x);
  6. // "2"
  7. alert(y);

1.2、数值的克隆

  1. var x=1;
  2. var y=x;
  3. y=2;
  4. // 1
  5. alert(x);
  6. // 2
  7. alert(y);

1.3、布尔值的克隆

  1. var x=true;
  2. var y=x;
  3. y=false;
  4. // true
  5. alert(x);
  6. // false
  7. alert(y);

2、合成类型对象的克隆

2.1、数组的克隆

如果采用普通克隆:

  1. var x=[1,2];
  2. var y=x;
  3. y.push(3);
  4. // 1,2,3
  5. alert(x);
  6. // 1,2,3
  7. alert(y);

由上可知,原始数组x,克隆数组y,修改了克隆数组y,但也同时修改了原始数组x,这就是引用对象的特点。那么如何才能达到完整的数组克隆呢?

  1. var x=[1,2];
  2. var y=[];
  3. var i=0;
  4. var j=x.length;
  5. for(;i<j;i++)
  6. {
  7. y[i]=x[i];
  8. }
  9. y.push(3);
  10. // 1,2
  11. alert(x);
  12. // 1,2,3
  13. alert(y);

这样,克隆数组y,原始数组x,两个数组互补干扰,实现了完整的数组克隆。

2.2、对象的克隆

和数组的克隆同理,对象的完整克隆如下:

  1. var x={1:2,3:4};
  2. var y={};
  3. var i;
  4. for(i in x)
  5. {
  6. y[i]=x[i];
  7. }
  8. y[5]=6;
  9. // Object {1: 2, 3: 4}
  10. console.log(x);
  11. // Object {1: 2, 3: 4, 5: 6}
  12. console.log(y);

2.3、函数的克隆

var x=function(){alert(1);};
var y=x;
y=function(){alert(2);}; // function(){alert(1);};
alert(x); // y=function(){alert(2);};
alert(y);

函数的克隆,使用“=”符号就可以了,并且在改变克隆后的对象,不会影响克隆之前的对象,因为克隆之后的对象会单独复制一次并存储实际数据的,是真实的克隆。

3、完整的对象克隆

根据1和2,总结一下完整的对象克隆,包括克隆普通对象、引用对象。在写这个方法之前,我们必须想到的是,克隆引用对象必须采用完整克隆(深度克隆),包括对象的值也是一个对象也要进行完整克隆(深度克隆)。

完整的对象克隆又称为深度对象克隆、对象的深度克隆、对象的深度复制等等。

  1. function clone(obj)
  2. {
  3. var o,i,j,k;
  4. if(typeof(obj)!="object" || obj===null)return obj;
  5. if(obj instanceof(Array))
  6. {
  7. o=[];
  8. i=0;j=obj.length;
  9. for(;i<j;i++)
  10. {
  11. if(typeof(obj[i])=="object" && obj[i]!=null)
  12. {
  13. o[i]=arguments.callee(obj[i]);
  14. }
  15. else
  16. {
  17. o[i]=obj[i];
  18. }
  19. }
  20. }
  21. else
  22. {
  23. o={};
  24. for(i in obj)
  25. {
  26. if(typeof(obj[i])=="object" && obj[i]!=null)
  27. {
  28. o[i]=arguments.callee(obj[i]);
  29. }
  30. else
  31. {
  32. o[i]=obj[i];
  33. }
  34. }
  35. }
  36. return o;
  37. }

4、参考资料

最新文章

  1. C#中的线程(一)入门
  2. php做登录注册页面及加载
  3. [MetaHook] SearchPattern function
  4. Bootstrap日期和时间表单组件运用兼容ie8
  5. dom添加事件
  6. jQuery中自定义简单动画的实现
  7. HDU 2722 Here We Go(relians) Again
  8. jstack:将Process Explorer中看到的进程ID做16进制转换,到ThreadDump中加上0x 前缀即能找到对应线程(转)
  9. 修改一个Label上字体的大小(富文本)
  10. linux 权限字母含义
  11. [bzoj4849][Neerc2016]Mole Tunnels
  12. 枚举、反射等 GetEnumName GetEnumDescription
  13. Delphi 10.3.1拍照遇到的问题
  14. Oracle相关内容整理
  15. python 的 json 转换
  16. 安装 Android Studio 2.3 详细过程及错误解决
  17. NetCore在Centos7上部署和Nginx集群部署访问
  18. springMVC介绍及配置
  19. 二十九、利用 IntelliJ IDEA 进行代码对比的方法
  20. 【Nginx】不改系统源代码的情况下,动态网站离线缓存方案

热门文章

  1. Android在layout xml中使用include完成静态加载
  2. phalcon: 开启模板缓存和缓存路径
  3. hadoop-0.20.1+120 hive-0.3.99.1+0 试用hwi(hive web interface
  4. python 实现一个TwoSum的例子
  5. Oracle常见的33个等待事件
  6. ios 加密解密(包括base64,DES)非原创
  7. 网络基础之网络协议篇---CS架构--网络通信--osi 协议---套接字socket--粘包
  8. java入门学习(1)一简介及其基础特点
  9. checking for event2/thread.h... no libevent_pthreads required, failing
  10. BZOJ - 1036 树的统计Count (树链剖分+线段树)