在 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>
分享到:
相关推荐
本文将深入探讨"深度克隆"这一概念,以及它与普通克隆的区别,并讨论其在实际应用中的优缺点。 深度克隆,也称为完全克隆,是一种创建新对象的技术,这个新对象不仅包含原始对象的所有属性值,还包含了嵌套对象的...
下面是一些关于`clone`的实践心得: 1. 注意权限:默认情况下,`clone`方法是`protected`的,这意味着在同一个包内的类才能直接调用。如果需要在不同包的类中使用`clone`,需要将它声明为`public`。 2. 避免空指针...
关于 git clone 下面说法正确的是
在标签"java clone()"中,我们可以推断这篇博客可能还讨论了关于Java中对象复制的各种策略,如序列化和反序列化,以及`CopyConstructor`,这些都是创建对象副本的替代方法,特别是当`clone()`不能满足特定需求时。...
Java中的`clone`方法是Java语言提供的一种复制对象的方式,它允许创建一个对象的副本,这个副本与原对象具有相同的属性值,但它们是两个独立的对象,修改副本不会影响原对象。`clone`方法存在于Java的`java.lang....
为了得到深拷贝,即完全独立的副本,你需要手动实现深度复制逻辑,例如,遍历引用类型字段并逐个复制每个元素。 总之,`clone()`方法在Java中提供了对对象复制的基本支持,尤其适用于需要创建对象副本的情况。然而...
在Java编程语言中,`clone`是一个非常重要的概念,它涉及到对象复制和对象的深拷贝与浅拷贝。本文将深入探讨Java中的`clone`方法及其相关知识点。 首先,`clone`方法是Java `Object`类的一个成员方法,定义为`...
### Java中的`clone`方法详解:浅拷贝与深拷贝 #### 一、引言 在Java中,`clone`方法提供了一种快速复制对象的方式。它属于`Object`类的一部分,但需要显式地在子类中声明并实现`Cloneable`接口才能正常使用。本文...
List的深度复制 浅谈C#中List<T>对象的深度拷贝问题
- `--depth `<n>`:限制克隆的历史深度,可以加快克隆速度,但只保留最近的n个提交。 - `--branch `<branch>`:克隆特定的分支而不是默认的主分支。 - `--single-branch`:仅克隆指定的分支,而不是所有分支。 - `--...
在Java中,克隆分为两种类型:浅克隆(Shallow Clone)和深度克隆(Deep Clone)。 1. 浅克隆(Shallow Clone) 浅克隆是Java克隆机制的默认行为。当一个对象被克隆时,如果它的成员变量是基本类型(如int、double...
以上就是关于 `git clone` 和 `git submodule` 命令以及如何使用它们来管理和维护项目中的子模块的详细介绍。这些命令对于处理大型项目或包含多个子项目的项目非常重要。熟练掌握这些命令可以帮助你更高效地管理工作...
3. **保存镜像**:用户可以选择保存这个镜像文件在硬盘上,以便后续使用。 4. **刻录镜像**:当需要时,用户可以选择这个镜像文件,并使用CLONE_CD将其刻录到空白CD上。 CLONE_CD支持多种CD格式,包括CD-Audio、CD-...
标题中的"jlink v9 warning clone解决"意味着开发者正在尝试解决关于JLink v9版本出现的克隆警告。这个警告可能是因为使用了非官方的或者未授权的JLink设备,或者是由于驱动程序或固件版本不兼容导致的。在MDK环境下...
go-clone:深度克隆任何Go数据 包clone提供了对任何Go数据进行深度克隆的功能。 它还提供了一个包装器,以保护指针免受任何意外的突变。 Clone / Slowly可以克隆任何结构的未导出字段。 明智地使用此功能。 安装 ...
解决 JLINK 固件丢失或升级固件后提示 Clone 的问题 在使用 JLINK 仿真器进行单片机开发时,可能会遇到固件丢失或升级固件后提示 Clone 的问题,本文将提供解决该问题的步骤。 问题描述 使用 JLINK 仿真器时,...
标题“CLONE 10-ex”以及描述“Clone10-EX-LV2”暗示了我们正在处理一个可能与克隆或复制技术相关的项目,可能是软件、系统镜像或者某种形式的数据备份工具。"Clone"通常指的是在计算机科学中创建一个与原始对象完全...
我们将讨论每个文件的作用,并提供相关知识点。 首先,`clone-all.bat`是用于批量克隆Git仓库的脚本。在Git中,`git clone`命令用于复制远程仓库到本地。批量克隆通常涉及循环遍历一个包含仓库URL的列表,然后依次...
"clone-voice.zip" 是一个压缩包文件,很可能包含了与语音克隆技术相关的代码或工具。根据提供的标签 "python",我们可以推测这个项目是使用Python编程语言实现的。Python在处理音频数据和人工智能领域有着广泛的...