Heim  >  Fragen und Antworten  >  Hauptteil

javascript - js深度复制一个对象使用JSON.stringify是最好的办法吗?

深度复制一个对象,看到很多种方法,最简单的是:

var newObject = JSON.parse(JSON.stringify(oldObject));

这样写有什么弊端吗?

PHPzPHPz2729 Tage vor864

Antworte allen(7)Ich werde antworten

  • 黄舟

    黄舟2017-04-10 14:37:47

    oldObject = {a: 1, b: function() {}}

    Antwort
    0
  • 天蓬老师

    天蓬老师2017-04-10 14:37:47

    var newObject = Object.create(oldObject);
    
    

    Antwort
    0
  • 怪我咯

    怪我咯2017-04-10 14:37:47

    一般情况下通过 JSON 来复制挺好的,代码写起来也方便——不过并不是所有环境都实现了 JSON,这个需要考虑下。

    通过 deep clone 一般都是有限定复制层次的,一般情况下不会无限层的复制下去。如果使用 JSON 方式来复制,通常不能控制层次。

    Antwort
    0
  • 大家讲道理

    大家讲道理2017-04-10 14:37:47

    深拷贝不就好了么。

    https://github.com/XadillaX/nbut-online-judge-v2/blob/master/util/functions.js#L7-L28

    /**
     * Deepin clone an object
     * @param obj
     * @returns {*}
     */
    exports.cloneObject = function(obj) {
        if(typeof obj === "object") {
            if(util.isArray(obj)) {
                var newArr = [];
                for(var i = 0; i < obj.length; i++) newArr.push(obj[i]);
                return newArr;
            } else {
                var newObj = {};
                for(var key in obj) {
                    newObj[key] = this.cloneObject(obj[key]);
                }
                return newObj;
            }
        } else {
            return obj;
        }
    };
    

    Antwort
    0
  • 伊谢尔伦

    伊谢尔伦2017-04-10 14:37:47

    可以参考一下stackoverflow上关于克隆一个对象的有效方法

    Antwort
    0
  • 天蓬老师

    天蓬老师2017-04-10 14:37:47

    使用JSON接口有弊端,使用Object.create不会复制对象本身, 而是用对象的constructor重新构造一个对象。
    所以可以考虑使用Object.assign

    let old_obj = [{a:1},{b:2}];
    let new_obj = old_obj.map((ele)=>{
        return Object.assign({},ele);
    });
    old_obj[0].a=99;
    console.log(new_obj); // "[{a:1},{b:2}]" 

    Antwort
    0
  • 巴扎黑

    巴扎黑2017-04-10 14:37:47

    这个看需求,我是搜索进来的,之前使用封装出来的深拷贝方法,结果不能满足我的需求,

    建议如果数据格式大而且多样的话,最好是用楼主说的方法; 如果deepcopy的层级小的话,可以看下面的代码:

    var hasOwn = Object.prototype.hasOwnProperty;
    function deepCopy(receiver, obj){
        var args = [].slice.call(arguments), key, i = 1, deep, ride, value, valueType;
    
        if( typeof args[args.length-2] === "boolean" ){
            deep = args.pop();
            ride = args.pop();
        }else{
            ride = (typeof args[args.length-1] === "boolean")?args.pop():true;
            deep = false;
            if(args.length < 2){
                receiver = ( this !== global ) ? this : {};
                if( args.length === 0 ){
                    return receiver;
                }
            }
        }
    
        while( obj = args[ i++ ] ){
            for( key in obj ){
                if( hasOwn.call(obj, key) ){
                    if( ride || !(key in receiver) ){
                        value = obj[key];
                        valueType = type(value);
                        if( deep && ( valueType==="object")){
                            receiver[key]={};
                            deepCopy(receiver[key], value, ride, deep);
                        }else if( deep && ( valueType==="array" )){
                            receiver[key]=[];
                            deepCopy(receiver[key], value, ride, deep);
                        }else{
                            receiver[key] = obj[key];
                        }
                    }
                }
            }
        }
        return receiver;
    }
    
    // 类型判定对象
    var class2type = {
        "[objectHTMLDocument]" : "document",
        "[objectHTMLCollection]" : "nodeList",
        "[objectStaticNodeList]" : "nodeList",
        "[objectIXMLDOMNodeList]" : "nodeList",
        "null" : "null",
        "NaN" : "NaN",
        "undefined" : "undefined"
    };
    
    "Boolean, Number, String, Function, Array, Date, RegExp, Document, Arguments, NodeList"
        .replace( /[^, ]+/g, function( type ){
            class2type["[object " + type + "]"] = type.toLowerCase();
        } );
    
    // 类型判定
    function type( obj, isType ){
        var key = ((obj == null || obj !== obj ) ? obj + "" : Object.prototype.toString.call( obj )),
            result;
    
        if( typeof(result = class2type[ key ]) !== "string" ){
            if( obj.nodeType === 9 ){
                result = class2type["Document"];
            }else if( obj.item && typeof obj.length === "number" ){
                result = class2type["NodeList"];
            }else{
                result = key.slice(8, -1);
            }
        }
    
    
        if( isType ){
            return result === isType.toLowerCase;
        }
    
    
        return result;
    }
    
    export { deepCopy };   //根据开发模式选择使用或不使用,可取消

    Antwort
    0
  • StornierenAntwort