Javascript-форум (https://javascript.ru/forum/)
-   Общие вопросы Javascript (https://javascript.ru/forum/misc/)
-   -   Клонирование объекта (https://javascript.ru/forum/misc/62192-klonirovanie-obekta.html)

olegyakovlev 28.03.2016 22:04

Клонирование объекта
 
Необходимо на typescript сделать метод для клонирования объекта. С учетом того, что элементы могут быть ссылкой на этот же объект

Код:

var obj: any = {
  x:{y: 'qwe'},
    y: "qwe"
};
obj['x']['a'] = obj;
obj['x']['b'] = obj['x'];

при "стандартном" методе не выйдет с рекурсии
Код:

function cloneObject(obj) {
    var clone = {};
    for (var i in obj) {
        if (typeof (obj[i]) == "object" && obj[i] != null) clone[i] = cloneObject(obj[i]);
      else clone[i] = obj[i];
    }
    return clone;
}

Как можно обойти такой вариант?

nerv_ 29.03.2016 00:21

olegyakovlev, писать свой велосипед. Например, можете использовать мой рекурсивный итератор и взять за основу пример из книги рецептов (Deep copy / Deep clone).

Яростный Меч 29.03.2016 00:21

var cloneObject = (function(global) {

    function ObjMap() {
        this._data = [];
    }
    ObjMap.prototype = {
        constructor: ObjMap,
        _get: function(key) {
            for (var i = 0; i < this._data.length; ++i) {
                if (this._data[i].key === key) {
                    return this._data[i];
                }
            }
            return null;
        },
        get: function(key) {
            var data = this._get(key);
            return data ? data.value : void(0);
        },
        set: function(key, value) {
            var data = this._get(key);
            if (data) {
                data.value = value;
            } else {
                this._data.push({ key: key, value: value });
            }
        }
    };
    
    function cloneObject(obj, map) {
        var clone = map.get(obj);
        if (clone) {
            return clone;
        }
        clone = {};
        map.set(obj, clone);
        for (var i in obj) {
            if (obj.hasOwnProperty(i)) {
                if (obj[i] && typeof obj[i] == "object") {
                    clone[i] = cloneObject(obj[i], map);
                } else {
                    clone[i] = obj[i];
                }
            }
        }
        return clone;
    }
    
    return function(obj) {
        var map = global.Map ? new Map() : new ObjMap();
        return cloneObject(obj, map);
    };
})(window);

Яростный Меч 29.03.2016 00:24

ещё надо добавить поддержку массивов, и возможно некоторых специальных объектов (функции, регексы и т.д.), но к циклам это не относится и в мой код не вошло, дабы не загромождать )

olegyakovlev 30.03.2016 10:33

Спасибо.
пока сделано следующее решение:
Код:

class NewObj {

arrOriginObj:Object[]=[];
arrNewObj:Object[]=[];

clone(objP:Object){

 for(let i=0; i< this.arrOriginObj.length;i++){
  if(objP===this.arrOriginObj[i])
    return this.arrNewObj[i];
  }
 
 let newObj={};
 this.arrNewObj.push(newObj);
 this.arrOriginObj.push(objP);
 
 for(let key in objP){
  if(objP.hasOwnProperty(key)) {
  if(objP[key] !== null && typeof(objP[key]) === "object" ) {
      newObj[key] = this.clone( objP[key] );
    }else
    newObj[key] = objP[key]; 
  }
 }
 return newObj;
}
}

объекты проходит)


Часовой пояс GMT +3, время: 19:39.