Javascript: сеттер и геттер объекта теряются после клонирования/копирования/расширения

Я хотел бы иметь возможность копировать объект, сохраняя getter и сеттера.

ПРИМЕЧАНИЕ. Этот вопрос касается angularjs, но он может относиться и ко многим другим фреймворкам.

Код доступен по адресу: https://jsfiddle.net/vwb04d4f/2/.

function out(str) {
    document.getElementById('body').innerHTML += str + "<br>";
}

var SomeObj = function () {
  var obj = {
    _val: 0,
    set val(value) {
       out("Set: " + value);
        this._val = value;
    },
    get val() {
        return this._val;
    }
  }
  return obj;
};

var sObj = new SomeObj();
sObj.val = 100;

var sCopy = angular.copy(sObj);
sCopy.val = 200;
out("Value:" + sCopy.val);

var sExt = angular.extend(sObj);
sExt.val = 300;

out("Value: " + sObj.val);

Выход:

Set: 100
Value:200
Set: 300
Value: 300

Почему «set val» больше не запускается после «angular.copy»? Как видите, значение сохранено корректно.

«angular.extend» сохраняет ссылки, поэтому обновление sExt приведет к обновлению sObj, чего я не хочу.

Я копирую объект области перед передачей его в контроллер (модальный):

    $modal.open({
      animation: true,
      templateUrl: '/html/settings.html',
      controller: 'ModalInstanceCtrl',
      backdrop: false,
      resolve: {
          config: function() {
                var cfgcpy = {};
                angular.copy($scope.config, cfgcpy);
                return cfgcpy;
          }
      }
    }).result.then(function(res){
        ok_func(res);
        close_func();
    }, function() {
        close_func();
    });

angular.module('app').controller('ModalInstanceCtrl', function ($scope, $modalInstance, config) {
  $scope.config = config;
  ...
});

Любые идеи о том, как скопировать sObj, не теряя «установить» и «получить» и не сохраняя ссылки?

** ОБНОВИТЬ:

Как указано в ссылке, предоставленной RichS, кажется, что причина в том, что свойства getter и setter не перечислимы и, следовательно, они не копируются. Этот вопрос тесно связан (или дублируется, если мы перейдем к источнику проблемы): объект с результатами геттеров

Я обновил код: https://jsfiddle.net/vwb04d4f/3/

Я добавил вручную свойство "перечисляемое":

var SomeObj = function () {
  var obj = {
    _val: 0 
  }
  Object.defineProperty(obj, "val", {
        enumerable: true,
        set : function(value) {
           out("Set: " + value);
           this._val = value;
        },
        get: function(){
            return this._val;
        }
  });
  return obj;
};

Однако ни расширение (из пустого объекта), ни копирование на самом деле не выполняют эту работу. Возможно, я что-то упускаю?

** ОБНОВЛЕНИЕ 2 **

Поскольку эта проблема связана не только с angularjs.


person lepe    schedule 19.10.2015    source источник
comment
github.com/angular/angular.js/issues/5085   -  person RichS    schedule 19.10.2015
comment
@RichS: Спасибо, что нашли эту ссылку! Это все объясняет... нам просто нужно какое-то решение? Кстати, я использую angular 1.4.4. Попробую с бета-версией.   -  person lepe    schedule 19.10.2015


Ответы (2)


Я нашел решение в этом вопросе: эффективный способ глубокого клонирования объекта в JavaScript?

function cloneObject(source) {
    var key,value;
    var clone = Object.create(source);

    for (key in source) {
        if (source.hasOwnProperty(key) === true) {
            value = source[key];

            if (value!==null && typeof value==="object") {
                clone[key] = cloneObject(value);
            } else {
                clone[key] = value;
            }
        }
    }
    return clone;
}

См. обновленный код здесь: https://jsfiddle.net/vwb04d4f/6/.

Как видите, «перечисление» не требуется. Пока этот код, похоже, решил мою проблему. Спасибо Стивену Вашону.

В этом вопросе есть много решений, я протестировал большинство из них, но не все.

person lepe    schedule 20.10.2015

это происходит из-за глубокого/мелкого:

«Ленивая копия — это комбинация мелкой и глубокой копии. При первоначальном копировании объекта используется (быстрая) неглубокая копия. Счетчик также используется для отслеживания того, сколько объектов совместно используют данные».

Прочтите это или проверьте это ответ, чтобы сделать его более понятным или даже угловатым документы

person macrog    schedule 19.10.2015