2016-12-31 2 views
0

Я довольно новичок в getters и seters и ищу способ прослушивания изменений в объекте для немедленного хранения данных без вызова функции Save() значение изменяется. Это, как я сделать это прямо сейчас:Использование getter и setter для свойства объекта, имеющего собственные свойства

var myObject = { 
    Data: { 
     enabled: true, 
     show: false 
    }, 
    Save: function() { 
     //store myObject.Data to local storage 
    }, 
    Load: function() { 
     //load data from local storage and assign it to myObject.Data 
    }, 
    doSomething: function() { 
     myObject.Load(); 
     if (myObject.Data.enabled) { 
      myObject.Data.show = true; 
      myObject.Save(); 
     } 
    } 

Теперь я хотел бы, чтобы оптимизировать этот код, чтобы каждый раз, когда свойство в myObject.Data изменяется, myObject.Save() выполняется. Проблема, с которой я сталкиваюсь, заключается в том, что, возможно, только можно определить getter для свойства, имеющего только одно значение, но не для свойства, которое является самим объектом.

var myObj = { 
    _Data: { 
     a: 0, 
     b: 1, 
     c: 3 
    }, 
    set Data (a) { 
     console.log(a); 
    } 
}; 

myObj.Data.a = 2; 

Это, очевидно, не работает, так как myObj.Data не является объектом и не обладают теми же свойствами, как myObj._Data.

Заранее благодарим за любую помощь.

ответ

3

Вы, вероятно, заинтересованы в Proxy объекта.

Я использовал очень простую функцию debounce callHandler, чтобы избежать вызова метода onSet десятками раз при модификации массива. В противном случае [1, 2, 3].splice(0, 1) будет вызывать обработчик набора один раз для элемента в исходном массиве.

'use strict'; 
 
var myObject = { 
 
    Data: { 
 
     a: [1, 2, 3], 
 
     b: {c: ['test']} 
 
    }, 
 
    Save: function() { 
 
     console.log('Save called'); 
 
    }, 
 
} 
 

 
function recursiveProxy(target, onSet) { 
 
    // For performance reasons, onSet will only be called one millesecond 
 
    // after the set handler has last been called. 
 
    var timeout; 
 
    function callHandler() { 
 
     clearTimeout(timeout); 
 
     timeout = setTimeout(onSet, 1); 
 
    } 
 

 
    var recursiveHandler = { 
 
     get: function(target, property) { 
 
      // If the property is something that could contain another object, 
 
      // we want to proxy it's properties as well. 
 
      if (typeof target[property] == 'object' && target[property] != null) { 
 
       return new Proxy(target[property], recursiveHandler); 
 
      } 
 

 
      return target[property]; 
 
     }, 
 
     set: function(target, property, value) { 
 
      console.log('Set called - queueing onSet'); 
 
      callHandler(); 
 
      target[property] = value; 
 
      return true; 
 
     } 
 
    } 
 

 
    return new Proxy(target, recursiveHandler); 
 
} 
 

 
myObject.Data = recursiveProxy(myObject.Data, myObject.Save); 
 

 
myObject.Data.a.splice(0, 1); 
 
myObject.Data.b.c[0] = 'test 2';

+0

Nice решение! Я не думаю, что нужно вернуть значение. – trincot

+0

Имейте в виду, что прокси-сервер ES6 + работает только в новом браузере, а NodeJS v6 + – DiegoRBaquero

+0

@trincot, предполагая строгий режим, это важно. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy/handler/set#Return_value – Gerrit0

0

Я считаю, что вы ищете Defining a getter on existing objects using defineProperty

Для добавления поглотителя к существующему объекту позже в любое время, используйте Object.defineProperty().

var o = { a:0 } 

Object.defineProperty(o, "b", { get: function() { return this.a + 1; } }); 

console.log(o.b) // Runs the getter, which yields a + 1 (which is 1) 

Для например:

var Data = { 
    enable: true, 
    show: false 
}; 

Object.defineProperty(Data, 'doSomething', { 
    get: function() { 
     // get something; 
    }, 
    set: function(something) { 
     // set something 
    } 
}); 
Смежные вопросы