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

clone的三种js实现

    博客分类:
  • JS
UI 
阅读更多

clone的三种js实现   

2009-11-17 08:37:54 |  分类: JavaScript技术 | 字号   订阅

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.js

    jquery.clone

    深入理解JavaScript中的对象复制(Object Clone)

    在深入探讨JavaScript中的对象复制(Object Clone)时,首先需要明确JavaScript中的对象复制分为浅复制(Shallow Copy)和深复制(Deep Copy)。浅复制指的是创建一个新对象,这个对象有着原始对象属性值的一份精确...

    github-clone-js:用JS编写的演示github客户端

    JavaScript是一种解释型的、基于原型的、多范式的脚本语言,主要应用于Web浏览器,但也可用于服务器端(如Node.js)和其他环境。它的核心特性包括变量、数据类型(如字符串、数字、布尔值、对象等)、控制结构(如...

    JS实现网页Div层Clone拖拽效果

    综上所述,通过本文的介绍,我们了解到利用JavaScript实现网页元素的拖拽效果实际上是一个涉及事件监听、元素属性动态设置、以及元素层级调整的综合技术。通过上述实例代码的分析,我们可以掌握如何实现复杂的网页...

    MS Paint Clone using JavaScript with Free Source Code.zip

    【标题】MS Paint Clone 使用JavaScript实现的免费源代码 在编程世界中,克隆经典应用程序是一种常见的学习方式,可以帮助开发者理解和实现类似功能。本项目是一个使用JavaScript语言复刻的MS Paint(微软画图)...

    js 实现 克隆表格

    js 实现 克隆表格! 值得下载看看!资源免费,大家分享!!

    Node.js-GitKit.js纯JavaScript实现的Git(支持Node.js和浏览器)

    2. **跨平台兼容**:由于是纯JavaScript实现,GitKit.js可以在Node.js和现代浏览器中运行,无需额外安装Git环境。 3. **内存存储或磁盘持久化**:根据应用场景,GitKit.js支持在内存中处理Git仓库,适合快速操作;...

    alibaba.com new PHP clone 英文版阿里巴巴克隆 PHP完整版源码

    `scripts.js`是JavaScript文件,可能包含了网站的前端交互逻辑,比如表单验证、动态加载内容和页面间的跳转。JavaScript与PHP结合,可以实现丰富的用户交互,提供更流畅的浏览体验。 `Alibaba2.htm`和`Alibaba.htm`...

    flow-clone-源码.rar

    在JavaScript中,由于其特有的原型链和引用类型,深拷贝和浅拷贝的概念尤为重要,"flow-clone"可能是实现深拷贝的一种解决方案。 解压"flow-clone-源码.zip"后,我们可以看到项目的组织结构。源码文件通常包含以下...

    javascript实现无缝循环

    JavaScript 实现无缝循环是前端开发中的一个常见需求,特别是在创建动态效果如轮播图时。无缝循环的关键在于创造一种视觉上的连续性,使得用户无法察觉到内容切换的断点。以下我们将深入探讨如何利用 JavaScript 来...

    jquery-clone-tableheader table 头部固定

    接着,需要引入"CloneTableHeader.js",这是实现头部固定的JavaScript代码,它包含了对表格进行处理和绑定事件的逻辑。 在HTML文件"CloneTable.html"中,我们通常会创建一个包含thead和tbody的表格结构。thead部分...

    Javascript对象Clone实例分析

    在讨论JavaScript对象克隆的实现与技巧时,我们首先需要了解对象克隆的概念和它在编程中的应用。对象克隆指的是创建一个具有与原始对象相同属性和值的新对象,但两个对象是独立的,即对新对象的任何修改都不会影响...

    JS 实例源代码 2014

    通过这些实例,你可以了解到如何利用JavaScript实现动态效果,如页面元素的增删改查、事件处理、AJAX请求等。此外,还能学习到错误处理、性能优化等实践经验,这对于提升JavaScript编程技能大有裨益。 总之,《JS...

    飘舞效果的三种实现方法FLASH

    本文将深入探讨如何使用Flash实现飘舞效果的三种方法,并重点关注其中涉及的复制函数在动画过程中的应用。 一、传统补间动画法 在Flash CS4及更早版本中,我们主要依靠补间动画来实现飘舞效果。首先,创建一个图形...

    htmljs克隆标签

    克隆HTML标签主要有两种方法:深克隆(deep clone)和浅克隆(shallow clone)。深克隆会复制元素及其所有子元素和属性,包括事件监听器;而浅克隆只会复制元素本身,不包含子元素和属性。 在JavaScript中,我们...

    深化理解JavaScript中的对象复制(Object Clone)_.docx

    在JavaScript中,有多种实现深复制的方法: 1. **jQuery的`$.extend()`方法**:在jQuery库可用的情况下,可以使用`$.extend()`进行深复制,但请注意,它不是专门为深复制设计的,所以对于某些复杂的数据结构可能不...

    JavaScript实现公告栏上下滚动效果

    步骤三:JavaScript实现 在JavaScript部分,我们首先通过jQuery选择器获取需要操作的元素,并使用`animate`方法为元素添加动画效果。在示例中,通过克隆第一个`<li>`元素并不断将其移动到`<ul>`的末尾,从而实现了...

    deep-clone:使用纯JS实现Deep Clone

    这是我使用纯JS深度克隆对象的实现。 在编码面试中经常被问到 :skull: ,很少在没有lodash之类的库的情况下使用。 支持以下测试用例(至少到目前为止我已经考虑过): 空对象(谁不想) 非对象 数组 简单对象...

    前端开源库-better-clone

    5. **兼容性**: `better-clone` 针对不同的 JavaScript 环境进行了优化,包括浏览器环境和 Node.js 环境,使得它在各种平台上都能稳定工作。 6. **API 简洁易用**: `better-clone` 提供了一个简单的 API,即 `...

Global site tag (gtag.js) - Google Analytics