検索

ホームページ  >  に質問  >  本文

在javascript里怎样方便的克隆一个object

最近在写程序的时候发现,如果在函数参数中传递一个object对象,如果我在函数内部改变了这个对象的字段值,那么这个对象也会随之改变,看来对于对象来说函数参数传递的是一个引用。

那么js里是否有方便的clone对象方法呢?我好像没有找到clone关键字支持,对象内部也没有clone方法,jQuery的$.clone方法也不能用在普通对象上,有这样的方法吗?

迷茫迷茫2894日前745

全員に返信(7)返信します

  • PHP中文网

    PHP中文网2017-04-10 12:46:08

    深拷贝需要考虑的因素非常多,比如

    • 传入的是普通的{}对象还是由构造函数生成的对象
    • 如果由构造函数生成是否拷贝原型链上的属性
    • 处理循环引用(包括自身引用)

    这里写出一个基本的深拷贝方案。只处理基本的{}对象,同时也处理Array,RegExp,Date,并解决循环引用问题。

    http://jsfiddle.net/cattail/NYNT5/

    返事
    0
  • PHP中文网

    PHP中文网2017-04-10 12:46:08

    可以使用 jQuery 中的 extend 方法。

    var o = {a: [1]};
    
    //浅拷贝
    var o1 = $.extend({}, o);
    console.log(o1.a === o.a);  // true
    
    //深拷贝
    var o2 = $.extend(true, {}, o);
    console.log(o2.a === o.a);  //false

    返事
    0
  • 黄舟

    黄舟2017-04-10 12:46:08

    表示 @cattail 这边给出的已经挺详细了。但是可能提问者没有说清楚自己的应用场景,因为我觉得JS编程一般这样深拷贝实例对象的场景不多。即便真的需要创造一个同样的实例对象,用这样深拷贝的方式是不妥的。

    因为,对于一个实例对象,我们可以将它分解为两部分
    1、实例对象本身的原型链
    2、实例对象自身的成员

    而原型链这边不管实例了多少个对象,都是共用的,因此clone无意义,唯一需要拷贝的是实例对象自身的成员。

    对于一个实例对象的自身成员,一般使用两种方式来设置
    1、构造函数
    2、setter方法

    因此针对实例对象的复制,最好的方式是,先取出需要进行拷贝的对象的数据,然后再利用这份数据来实例化和设置一个新的对象出来。

    var Foo = function( obj ){
        this.name = obj.name;
        this.sex = obj.sex
    };
    
    Foo.prototype.toJSON = funciton(){
        return { name: this.name, sex: this.sex };
    };
    
    var foo = new Foo({ name: "neekey", sex: "male" });
    var fooCopy = new Foo( foo.toJSON() );

    另外,如果对于纯数据对象(其实在这块的需要clone的场景会比较多),递归复制来clone其实很好写,不过如果你嫌麻烦,更简单的方式可以直接先JSON序列化,然后再解析回来:

    function copy( obj ){
        // JSON解析之类的其实如果给定格式不对很容易出错滴,自己做好检验~
        return JSON.parse( JSON.stringify( obj ) );
    }
    var data = { name: "neekey", sex: "male" }
    var dataCopy = copy( data );

    返事
    0
  • 高洛峰

    高洛峰2017-04-10 12:46:08

    JavaScript中对象拷贝分两种,浅拷贝与深拷贝,这里你提到的是深拷贝。

    对于一个普通的字面量对象,可以这样简单拷贝:

    function clone(myObj){  
        if(typeof(myObj) != 'object' || myObj == null) return myObj;  
        var newObj = new Object();  
        for(var i in myObj){  
          newObj[i] = clone(myObj[i]); 
        }  
        return newObj;  
    }  

    更多的参考:

    1. @cattail 的评论
    2. http://www.css88.com/archives/4818
    3. Google

    返事
    0
  • 大家讲道理

    大家讲道理2017-04-10 12:46:08

    简单copy可以用 for-in 循环就可以。
    深度copy,个人比较建议使用原型链,需要根据实际应用决定。

    返事
    0
  • ringa_lee

    ringa_lee2017-04-10 12:46:08

    js中函数参数都是按值传递的,即使函数局部改变引起了全局的改变。javascript高级程序设计里是这么说的,可是js里对象哪里有值传递啊。。。
    直接传值的话,又哪来的深复制浅复制啊。搞不懂了
    function setName(obj) {
    obj.name = 'obj';
    obj = new Object();
    obj.name = 'obj2';
    }

    var person = new Object();
    setName(person);
    console.log(person.name);//obj

    返事
    0
  • PHPz

    PHPz2017-04-10 12:46:08

    感觉、、、、$.extend()是可以的。。。。

    返事
    0
  • キャンセル返事