Лучший способ клонировать наблюдаемые?

Каков наилучший способ клонирования объектов Observable в Knockout для создания механизма транзакций?

Например, отредактируйте эту модель:

var Action = function (name, ownerType, condition, expression, args) {
    var self = this;
    this.name = ko.observable(name);
    this.ownerType = ko.observable(ownerType);
    this.condition = ko.observable(condition);
    this.expression = ko.observable(expression);
    this.args = ko.observable(args);
};

Я хочу сохранить состояние этого объекта, прежде чем пользователь его отредактирует. И если пользователь отменит редактирование - состояние отката объекта.

Самый простой способ - создать другой проект, например:

self.tempAction = new Action(action.name(), action.ownerType(), action.condition(), action.expression(), action.args());

Но я не уверен, что это изящное решение.

Итак, любые идеи?

Ответ 1

Я обычно делаю что-то вроде следующего:

Сначала у меня есть функция, которая имитирует функцию jQuery $.extend. Он заполняет объект target всеми значениями свойств observable (или не наблюдаемых) объекта source.

// extends observable objects intelligently
ko.utils.extendObservable = function ( target, source ) {
    var prop, srcVal, isObservable = false;

    for ( prop in source ) {

        if ( !source.hasOwnProperty( prop ) ) {
            continue;
        }

        if ( ko.isWriteableObservable( source[prop] ) ) {
            isObservable = true;
            srcVal = source[prop]();
        } else if ( typeof ( source[prop] ) !== 'function' ) {
            srcVal = source[prop];
        }

        if ( ko.isWriteableObservable( target[prop] ) ) {
            target[prop]( srcVal );
        } else if ( target[prop] === null || target[prop] === undefined ) {

            target[prop] = isObservable ? ko.observable( srcVal ) : srcVal;

        } else if ( typeof ( target[prop] ) !== 'function' ) {
            target[prop] = srcVal;
        }

        isObservable = false;
    }
    return target;
};

Затем у меня есть функция copy, которая по существу преобразует объект, который нужно скопировать в JSON, а затем берет JSON копию и создает новый объект javascript. Это гарантирует, что все указатели памяти не копируются, и у вас есть новый объект, который соответствует вашему оригинальному. Один из ключевых заключается в том, что вам нужно пройти в пустой экземпляр нового объекта (иначе мы бы не имели представления о том, какие свойства заполнить)

// then finally the clone function
ko.utils.clone = function(obj, emptyObj){
    var json = ko.toJSON(obj);
    var js = JSON.parse(json);

    return ko.utils.extendObservable(emptyObj, js);
};

Затем вы можете использовать его так:

var tempAction = ko.utils.clone(action, new Action());