`
zTreeAPI
  • 浏览: 345661 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

关于深度 clone 的后续讨论

阅读更多

在 zTree v3.5 发布之前看到了 [愚人码头] 的一篇文章《JavaScript深度克隆(深度拷贝)一个对象》,觉得 zTree 中的 clone 方法是应该适当优化一下,看着优化后的代码的确很简洁,大概测试无误,简单修正一下后,就直接拿了过来。

 

后来想了想,其实有时候代码也不能绝对为了优雅而忽略了性能,所以今天做了个简单的性能测试。

 

在测试过程中发现新代码虽然优雅,但效率却要略低于原先的代码,这让我很诧异,经过分析原来是

 

if(obj.hasOwnProperty(i)){...}
这个判断在作怪,每个属性在复制前都要判断一下,自然影响了效率。而且这句话还会产生另一个隐患——对于继承出来的对象在 clone 时会导致继承的属性全部被丢掉了。(对比了一下 jQuery 的extend 方法,clone 对象后是不会丢掉继承的属性的) 所以 果断删除这一句,删除后,效率与原先代码没有什么差异了。(这个修正会在 v3.5.01 中一起发布的,对于 zTree 的节点数据来说应该是不会有这方面影响的)

 

同时,对于有些朋友推崇的最精简的方法做了性能比较(这里暂不讨论这个方法有其他一些隐患以及兼容方面的问题)

 

JSON.parse(JSON.stringify(obj))

真的很简练的方法,但是他的效率只能达到咱们自己写的clone 方法的 一半;其实原因也很明显,先要遍历一遍 JSON 对象,把它转为 string;然后再把 string 转为 JSON 对象,同样的工作做了两遍,自然效率减半了。

 

我并不想强调你一定要用哪种方法,具体问题还是需要具体分析,只是想说明大家再决定采用什么方法的时候,还是要多考虑一些因素:代码的优雅、效率、兼容性 等等,选择适合自己的方法就可以了。

 

完整代码如下:

<!DOCTYPE HTML>
<html>
  <head>
    <title>CLONE TEST</title>
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
	<script type="text/javascript">
		//zTree 原先的 clone 方法
		function cloneOld (jsonObj) {
			var buf;
			if (jsonObj instanceof Array) {
				buf = [];
				var i = jsonObj.length;
				while (i--) {
					buf[i] = arguments.callee(jsonObj[i]);
				}
				return buf;
			}else if (typeof jsonObj == "function"){
				return jsonObj;
			}else if (jsonObj instanceof Object){
				buf = {};
				for (var k in jsonObj) {
					buf[k] = arguments.callee(jsonObj[k]);
				}
				return buf;
			}else{
				return jsonObj;
			}
		}
		//zTree 使用更简洁的 clone 方法
		function cloneNew (obj) {
			if (obj === null) return null;
			var o = obj.constructor === Array ? [] : {};
			for(var i in obj){
				//测试中可以打开 if 语句,看看效率的变化
//				if(obj.hasOwnProperty(i)){
					o[i] = (obj[i] instanceof Date) ? new Date(obj[i].getTime()) : (typeof obj[i] === "object" ? arguments.callee(obj[i]) : obj[i]);
//				}
			}
			return o;
		}
		//最精简的 clone 方法
		function cloneSimple (obj) {
			return JSON.parse(JSON.stringify(obj));
		}
		//测试方法
		function testClone(clone) {
			var i, times = 1000, start = new Date();
			for (i=0; i<times; i++) {
				clone(testCase);
			}
			var end = new Date();
			console.log(clone.name + " use " + (end.getTime() - start.getTime()));
		}

		var testCase = [], curId=1, maxLevel=3, num=4;
		//初始化测试数据
		function makeCase (list, level) {
			var i;
			for (i=0; i<num; i++) {
				var obj = {
					id : curId,
					level : level,
					name : "testItem_" + curId,
					title : "test Title " + curId
				};
				curId++;
				if (level < maxLevel) {
					obj.children = [];
					makeCase(obj.children, level+1);
				}
				list.push(obj);
			}
		}
		makeCase(testCase, 1);
	</script>
  </head>
  <body>
	  <button type="button" onclick="testClone(cloneOld)">Test Clone Old</button>
	  <button type="button" onclick="testClone(cloneNew)">Test Clone New</button>
	  <button type="button" onclick="testClone(cloneSimple)">Test Clone Simple</button>
  </body>
</html>
 

 

 

分享到:
评论
1 楼 archy123 2012-11-29  
性能>功能>美观

相关推荐

    clone 深度克隆对象

    本文将深入探讨"深度克隆"这一概念,以及它与普通克隆的区别,并讨论其在实际应用中的优缺点。 深度克隆,也称为完全克隆,是一种创建新对象的技术,这个新对象不仅包含原始对象的所有属性值,还包含了嵌套对象的...

    java clone

    下面是一些关于`clone`的实践心得: 1. 注意权限:默认情况下,`clone`方法是`protected`的,这意味着在同一个包内的类才能直接调用。如果需要在不同包的类中使用`clone`,需要将它声明为`public`。 2. 避免空指针...

    关于 git clone 下面说法正确的是

    关于 git clone 下面说法正确的是

    clone()示例源码

    在标签"java clone()"中,我们可以推断这篇博客可能还讨论了关于Java中对象复制的各种策略,如序列化和反序列化,以及`CopyConstructor`,这些都是创建对象副本的替代方法,特别是当`clone()`不能满足特定需求时。...

    java Clone

    Java中的`clone`方法是Java语言提供的一种复制对象的方式,它允许创建一个对象的副本,这个副本与原对象具有相同的属性值,但它们是两个独立的对象,修改副本不会影响原对象。`clone`方法存在于Java的`java.lang....

    java clone的小例子

    为了得到深拷贝,即完全独立的副本,你需要手动实现深度复制逻辑,例如,遍历引用类型字段并逐个复制每个元素。 总之,`clone()`方法在Java中提供了对对象复制的基本支持,尤其适用于需要创建对象副本的情况。然而...

    关于java clone的一些基本的概念

    在Java编程语言中,`clone`是一个非常重要的概念,它涉及到对象复制和对象的深拷贝与浅拷贝。本文将深入探讨Java中的`clone`方法及其相关知识点。 首先,`clone`方法是Java `Object`类的一个成员方法,定义为`...

    java_clone用法

    ### Java中的`clone`方法详解:浅拷贝与深拷贝 #### 一、引言 在Java中,`clone`方法提供了一种快速复制对象的方式。它属于`Object`类的一部分,但需要显式地在子类中声明并实现`Cloneable`接口才能正常使用。本文...

    List Clone.zip_c list深度复制_list clone_list的深度复制 C#

    List的深度复制 浅谈C#中List&lt;T&gt;对象的深度拷贝问题

    git clone 最新版

    - `--depth `&lt;n&gt;`:限制克隆的历史深度,可以加快克隆速度,但只保留最近的n个提交。 - `--branch `&lt;branch&gt;`:克隆特定的分支而不是默认的主分支。 - `--single-branch`:仅克隆指定的分支,而不是所有分支。 - `--...

    浅析Java中clone()方法浅克隆与深度克隆

    在Java中,克隆分为两种类型:浅克隆(Shallow Clone)和深度克隆(Deep Clone)。 1. 浅克隆(Shallow Clone) 浅克隆是Java克隆机制的默认行为。当一个对象被克隆时,如果它的成员变量是基本类型(如int、double...

    git代码clone,submodule

    以上就是关于 `git clone` 和 `git submodule` 命令以及如何使用它们来管理和维护项目中的子模块的详细介绍。这些命令对于处理大型项目或包含多个子项目的项目非常重要。熟练掌握这些命令可以帮助你更高效地管理工作...

    比nero更完美的刻录CD软件---CLONE_CD

    3. **保存镜像**:用户可以选择保存这个镜像文件在硬盘上,以便后续使用。 4. **刻录镜像**:当需要时,用户可以选择这个镜像文件,并使用CLONE_CD将其刻录到空白CD上。 CLONE_CD支持多种CD格式,包括CD-Audio、CD-...

    jlink v9 warning clone解决

    标题中的"jlink v9 warning clone解决"意味着开发者正在尝试解决关于JLink v9版本出现的克隆警告。这个警告可能是因为使用了非官方的或者未授权的JLink设备,或者是由于驱动程序或固件版本不兼容导致的。在MDK环境下...

    go-clone:深度克隆任何Go数据

    go-clone:深度克隆任何Go数据 包clone提供了对任何Go数据进行深度克隆的功能。 它还提供了一个包装器,以保护指针免受任何意外的突变。 Clone / Slowly可以克隆任何结构的未导出字段。 明智地使用此功能。 安装 ...

    关于JLINK固件丢失或升级固件后提示Clone的解决办法

    解决 JLINK 固件丢失或升级固件后提示 Clone 的问题 在使用 JLINK 仿真器进行单片机开发时,可能会遇到固件丢失或升级固件后提示 Clone 的问题,本文将提供解决该问题的步骤。 问题描述 使用 JLINK 仿真器时,...

    CLONE 10-ex

    标题“CLONE 10-ex”以及描述“Clone10-EX-LV2”暗示了我们正在处理一个可能与克隆或复制技术相关的项目,可能是软件、系统镜像或者某种形式的数据备份工具。"Clone"通常指的是在计算机科学中创建一个与原始对象完全...

    windows git 批量 clone 脚本

    我们将讨论每个文件的作用,并提供相关知识点。 首先,`clone-all.bat`是用于批量克隆Git仓库的脚本。在Git中,`git clone`命令用于复制远程仓库到本地。批量克隆通常涉及循环遍历一个包含仓库URL的列表,然后依次...

    clone-voice.zip

    "clone-voice.zip" 是一个压缩包文件,很可能包含了与语音克隆技术相关的代码或工具。根据提供的标签 "python",我们可以推测这个项目是使用Python编程语言实现的。Python在处理音频数据和人工智能领域有着广泛的...

Global site tag (gtag.js) - Google Analytics