在 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>
分享到:
相关推荐
arcgis Pro深度学习环境部署教程,clone一个名字为plam-detection的工程环境;clone的位置在C:\Users\admin\AppData\Local\ESRI\conda\envs可以去在Pro的project下切换环境。(安装完Pro后默认的conda的环境位置:C:...
深度克隆对象,不过效率没有显示的new对象快,不过很安全
List的深度复制 浅谈C#中List<T>对象的深度拷贝问题
Clone 属性的相关内容 Clone 属性的相关内容
git clone 最新版 不多说上资源 好用测试ok git clong git clone 最新版 不多说上资源 好用测试ok git clong
对java clone的一些讲解,以及我个人的一些心得等等,
主要介绍了Java利用序列化实现对象深度clone的方法,实例分析了java序列化及对象克隆的相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下
Clone10-EX-LV2
jquery.clone
java中clone的详细用法,分浅拷贝和深拷贝,并分别有详细的实例介绍。从原理分析。
Minesweeper CLone 0.97 Saolei.net扫雷网,小门汉化 Men Shiyun Mine.exe 请自行下载MinesweeperClone_0.97.exe安装后使用
支持多个git库clone,提交等常用操作,用户需要根据实际情况微调参数
详细的描述了Java中 clone方法使用
用 Java 语言编写的 初学者可学习的clone()
在使用高版本版KEIL时,提示要升级固件,升级后就出现JLINK is Clone的提示!“the emulator is JLink-Clone, the segger software only support orginal segger device” 然后闪退,IDE崩溃关闭! 解决方案: 1....
compass git clone compass git clone
Jlink-clone解决办法,替换文件
git-fastclone, 关于类固醇,git clone 递归 fastclone git fastclone是类固醇的git clone --recursive 。为什么 fastclone?在特定机器上进行大量重复签出?知识库 1st Fastclone 2nd Fastc
Jlink v8固件修复或解决Clone问题,内有固件下载地址。
当项目很大,有一些很大的文件存在时,clone远程仓库代码可能会失败,clone下来的项目不完整,很可能是因为项目中的文件clone不全,这个工具可以解决这个问题