How to Deep clone in javascript

前端 未结 19 1465
-上瘾入骨i
-上瘾入骨i 2020-11-22 02:06

How do you deep clone a JavaScript object?

I know there are various functions based on frameworks like JSON.parse(JSON.stringify(o)) and $.extend(t

19条回答
  •  南笙
    南笙 (楼主)
    2020-11-22 02:55

    As others have noted on this and similar questions, cloning an "object", in the general sense, is dubious in JavaScript.

    However, there is a class of objects, which I call "data" objects, that is, those constructed simply from { ... } literals and/or simple property assignments or deserialized from JSON for which it is reasonable to want to clone. Just today I wanted to artificially inflate data received from a server by 5x to test what happens for a large data set, but the object (an array) and its children had to be distinct objects for things to function correctly. Cloning allowed me to do this to multiply my data set:

    return dta.concat(clone(dta),clone(dta),clone(dta),clone(dta));
    

    The other place I often end up cloning data objects is for submitting data back to the host where I want to strip state fields from the object in the data model before sending it. For example, I might want to strip all fields starting with "_" from the object as it is cloned.

    This is the code I ended up writing to do this generically, including supporting arrays and a selector to choose which members to clone (which uses a "path" string to determine context):

    function clone(obj,sel) {
        return (obj ? _clone("",obj,sel) : obj);
        }
    
    function _clone(pth,src,sel) {
        var ret=(src instanceof Array ? [] : {});
    
        for(var key in src) {
            if(!src.hasOwnProperty(key)) { continue; }
    
            var val=src[key], sub;
    
            if(sel) {
                sub+=pth+"/"+key;
                if(!sel(sub,key,val)) { continue; }
                }
    
            if(val && typeof(val)=='object') {
                if     (val instanceof Boolean) { val=Boolean(val);        }
                else if(val instanceof Number ) { val=Number (val);        }
                else if(val instanceof String ) { val=String (val);        }
                else                            { val=_clone(sub,val,sel); }
                }
            ret[key]=val;
            }
        return ret;
        }
    

    The simplest reasonable deep-clone solution, assuming a non-null root object and with no member selection is:

    function clone(src) {
        var ret=(src instanceof Array ? [] : {});
        for(var key in src) {
            if(!src.hasOwnProperty(key)) { continue; }
            var val=src[key];
            if(val && typeof(val)=='object') { val=clone(val);  }
            ret[key]=val;
            }
        return ret;
        }
    

提交回复
热议问题