clone的三种js实现
在js中,clone方法的实现并不困难,对js的6种基本类型来说 string boolean undefined null number皆可直接用=赋值,唯一麻烦的是object。
对object 我们可以用clone其所有成员的方式复制 作为方法的函数可以这样定义:
Co
de:
function clone()
{
var ret=new Object();
for(var p in this)
{
ret[p]=this[p];
}
}
但我们显然面对着一个问题:this[p]也可能是一个object 所以很可能我们需要用递归来实现deepClone
Code:
function deepClone()
{
var ret=new Object();
for(var p in this)
{
ret[p]=deepClone.call(this[p]);
}
}
对js来说实现clone还有另外一种方式,在javascript中,构造器的prototype属性指明了某一类的原型,当实例化时,这一原型被作为对象的原型使用。特别地,这个prototype对象也可能是从某一原型构造出来的,这形成了一个类似继承的结构,所以javascript的面向原型特性又被称作原型继承(尽管我很不赞同这种做法,还是要提一下)。
回到我们前面的Prototype Pattern,javascript天生的引用型原型继承为我们提供了另外一种clone的实现方式:
Code:
function prototypeClone()
{
var tmp=function(){};
tmp.prototype=this;
return new tmp;
}
这样clone出来的对象只读地共享一个原型的属性,它的最大优势是速度非常快,当我们希望快速复制大型对象时,可以使用这种方式,但是它会造成访问速度降低,而且它实时反映父节点的变化。
内置对象的clone
但是,到这里为止,我们还没有考虑内置对象,内置对象不能用普通方法clone 我们要考虑的内置对象有这么几个:
Function Array String Boolean Number Date
RegExp Error和Math没有需要clone的场景 所以不在我们的考虑之中。
对Function来说,完全产生一个副本是不可能的,因为我们无法保证构造的函数跟原来的函数在同一作用域,但是不包含作用域的实现是很容易的:
eval(this);
或者使用Function构造
return Function(new String("return ")+this)();
Function本身是个Object 因此必须加上Object的clone 实现functionPrototypeClone需要一点小花招
Code:
function functionClone()
{
var ret=Function(new String("return ")+this)();
for(var p in this)
{
ret[p]=this[p];
}
}
function functionDeepClone()
{
var ret=Function(new String("return ")+this)()
for(var p in this)
{
ret[p]=deepClone.call(this[p]);
}
}
function functionPrototypeClone()
{
var tmp=Function.prototype;
Function.prototype=this;
var ret=(new Function(new String("return ")+this))();
Function.prototype=tmp;
return ret;
}
Array只要保证length正确就可以了
Code:
function arrayClone()
{
var ret=new Array();
for(var p in this)
{
ret[p]=this[p];
}
}
function arrayDeepClone()
{
var ret=new Array();
for(var p in this)
{
ret[p]=deepClone.call(this[p]);
}
}
function arrayPrototypeClone()
{
var tmp=Array.prototype;
Array.prototype=this;
var ret=new Array();
Array.prototype=tmp;
return ret;
}
Date对象提供了getTime 所以可以很容易实现
Code:
function arrayClone()
{
var ret=new Date();
ret.setTime(this.getTime());
for(var p in this)
{
ret[p]=this[p];
}
}
function arrayDeepClone()
{
var ret=new Date();
ret.setTime(this.getTime());
for(var p in this)
{
ret[p]=deepClone.call(this[p]);
}
}
function arrayPrototypeClone()
{
var tmp=Date.prototype;
Date.prototype=this;
var ret=new Date();
ret.setTime(this.getTime());
Date.prototype=tmp;
return ret;
}
String Boolean Number都是只读的对象,所以只要=就可以了。
前
面讨论了三种Clone的实现方法,它们各自具有适合的语义环境,比如对一个数组来说 若是把它理解为一个集合Collection
则应该使用浅clone(假如集合A是B的子集,则应保证A.clone()亦是B的子集),若是把它理解为一个向量Vector,则应使用深
clone(保证对向量A的分量操作不应影响向量A.clone()的分量)。prototypeClone的一个最常见的应用场景是深度优先搜索算法算
法,为了扩展解空间树,我们通常需要快速的构造一个副本,如果使用clone或者deepClone
这将非常慢,而深度优先搜索的特点是在字节点被销毁之前,父节点不会变化,所以prototypeClone是非常合适的。
附:Prototype-oriented Programming和Prototype Pattern
面
向原型的语言思想跟原型模式是完全一致的:从同一原型clone出来的对象就是一类对象。Prototype-oriented的语言对这种模式提供了语
言级别的支持,即所有"类"的定义都是通过指定该类的一个原型来实现的(Class-Based
Programming是通过类结构声明来描述一类对象,meta-class则是通过构造一个"类对象"来描述一类对象)。每次实例话就clone一次
原型,然而这种方式会造成信息的冗余:所有对象都持有原型对象的一个clone的副本,而且一旦某一对象被构造,修改原型不会对它造成任何影响,这对于希
望在程序中统一改变某一类对象的人来说很不方便。于是,一种变通的方法产生了:引用型原型对象,与之相对,原来的原型对象使用方法被称为复制型原型对象。
引用型原型对象不再clone原型,而是保存一个指向原型的指针,当访问属性时,首先检查自己的属性,当查到不存在时,则通过指针向原型索取相应属性。而
引用型原型就是javascript的面向原型特性的实现方式。
分享到:
相关推荐
jquery.clone
在深入探讨JavaScript中的对象复制(Object Clone)时,首先需要明确JavaScript中的对象复制分为浅复制(Shallow Copy)和深复制(Deep Copy)。浅复制指的是创建一个新对象,这个对象有着原始对象属性值的一份精确...
JavaScript是一种解释型的、基于原型的、多范式的脚本语言,主要应用于Web浏览器,但也可用于服务器端(如Node.js)和其他环境。它的核心特性包括变量、数据类型(如字符串、数字、布尔值、对象等)、控制结构(如...
综上所述,通过本文的介绍,我们了解到利用JavaScript实现网页元素的拖拽效果实际上是一个涉及事件监听、元素属性动态设置、以及元素层级调整的综合技术。通过上述实例代码的分析,我们可以掌握如何实现复杂的网页...
步骤三:JavaScript实现 在JavaScript部分,我们首先通过jQuery选择器获取需要操作的元素,并使用`animate`方法为元素添加动画效果。在示例中,通过克隆第一个`<li>`元素并不断将其移动到`<ul>`的末尾,从而实现了...
【标题】MS Paint Clone 使用JavaScript实现的免费源代码 在编程世界中,克隆经典应用程序是一种常见的学习方式,可以帮助开发者理解和实现类似功能。本项目是一个使用JavaScript语言复刻的MS Paint(微软画图)...
js 实现 克隆表格! 值得下载看看!资源免费,大家分享!!
2. **跨平台兼容**:由于是纯JavaScript实现,GitKit.js可以在Node.js和现代浏览器中运行,无需额外安装Git环境。 3. **内存存储或磁盘持久化**:根据应用场景,GitKit.js支持在内存中处理Git仓库,适合快速操作;...
`scripts.js`是JavaScript文件,可能包含了网站的前端交互逻辑,比如表单验证、动态加载内容和页面间的跳转。JavaScript与PHP结合,可以实现丰富的用户交互,提供更流畅的浏览体验。 `Alibaba2.htm`和`Alibaba.htm`...
在JavaScript中,由于其特有的原型链和引用类型,深拷贝和浅拷贝的概念尤为重要,"flow-clone"可能是实现深拷贝的一种解决方案。 解压"flow-clone-源码.zip"后,我们可以看到项目的组织结构。源码文件通常包含以下...
JavaScript 实现无缝循环是前端开发中的一个常见需求,特别是在创建动态效果如轮播图时。无缝循环的关键在于创造一种视觉上的连续性,使得用户无法察觉到内容切换的断点。以下我们将深入探讨如何利用 JavaScript 来...
接着,需要引入"CloneTableHeader.js",这是实现头部固定的JavaScript代码,它包含了对表格进行处理和绑定事件的逻辑。 在HTML文件"CloneTable.html"中,我们通常会创建一个包含thead和tbody的表格结构。thead部分...
在讨论JavaScript对象克隆的实现与技巧时,我们首先需要了解对象克隆的概念和它在编程中的应用。对象克隆指的是创建一个具有与原始对象相同属性和值的新对象,但两个对象是独立的,即对新对象的任何修改都不会影响...
通过这些实例,你可以了解到如何利用JavaScript实现动态效果,如页面元素的增删改查、事件处理、AJAX请求等。此外,还能学习到错误处理、性能优化等实践经验,这对于提升JavaScript编程技能大有裨益。 总之,《JS...
本文将深入探讨如何使用Flash实现飘舞效果的三种方法,并重点关注其中涉及的复制函数在动画过程中的应用。 一、传统补间动画法 在Flash CS4及更早版本中,我们主要依靠补间动画来实现飘舞效果。首先,创建一个图形...
克隆HTML标签主要有两种方法:深克隆(deep clone)和浅克隆(shallow clone)。深克隆会复制元素及其所有子元素和属性,包括事件监听器;而浅克隆只会复制元素本身,不包含子元素和属性。 在JavaScript中,我们...
在JavaScript中,有多种实现深复制的方法: 1. **jQuery的`$.extend()`方法**:在jQuery库可用的情况下,可以使用`$.extend()`进行深复制,但请注意,它不是专门为深复制设计的,所以对于某些复杂的数据结构可能不...
这是我使用纯JS深度克隆对象的实现。 在编码面试中经常被问到 :skull: ,很少在没有lodash之类的库的情况下使用。 支持以下测试用例(至少到目前为止我已经考虑过): 空对象(谁不想) 非对象 数组 简单对象...
5. **兼容性**: `better-clone` 针对不同的 JavaScript 环境进行了优化,包括浏览器环境和 Node.js 环境,使得它在各种平台上都能稳定工作。 6. **API 简洁易用**: `better-clone` 提供了一个简单的 API,即 `...