Using the object located in the code below, you can achieve it quite easily:
function Fence() { // constructor } Fence.prototype.refresh = function() { // change the refresh code here console.log(this.x1 + "," + this.y1 + "," + this.x2 + "," + this.y2); }; // must be called after the prototype.refresh function is defined RefreshExtender.addRefreshProperties(Fence, [ new RefreshExtender.Property("x1", 0), // propertyName, defaultValue[, refreshFunction] new RefreshExtender.Property("y1", 0, function() { console.log('Refresh only y1 property.'); }), new RefreshExtender.Property("x2", 0), new RefreshExtender.Property("y2", 0) ]);
Then when using it:
var fence = new Fence(); fence.x1 = 20;
Now, if you change several properties at once, it will call the update function only after all the properties are set. For instance:
fence.x1 = 10; fence.x2 = 20; // Outputs: "10,0,20,0 (Outputs only ONCE)"
If we update the y1 property, it will execute the passed function when the property is created:
fence.y1 = 30; // Outputs: "Refresh only y1 property."
Update expander:
var RefreshExtender = { addRefreshProperties: function(baseType, properties) { function defineProperty(property) { Object.defineProperty(baseType.prototype, property.name, { get: function() { var val = this["_" + property.name]; if (typeof val === "undefined") { return property.defaultValue; } return val; }, set: function(val) { var shouldRefresh = this["_" + property.name] !== val; this["_" + property.name] = val; if (shouldRefresh) { if (typeof property.refreshFunction === "function") { property.refreshFunction(); } else { this.refresh(); } } }, enumerable: true, configurable: true }); } for (var i = 0, l = properties.length; i < l; i++) { defineProperty(properties[i]); } var oldRefreshFunction = baseType.prototype.refresh; baseType.prototype.refresh = RefreshExtender._executeOnce(oldRefreshFunction); }, Property : function(name, defaultValue, refreshFunction) { this.name = name; this.defaultValue = defaultValue; if (typeof refreshFunction === "function") { this.refreshFunction = RefreshExtender._executeOnce(refreshFunction); } }, _executeOnce : function(originalFunc) { var isRefreshing = false, func = function() { var _this = this; if (!isRefreshing) { isRefreshing = true; setTimeout(function() { isRefreshing = false; originalFunc.call(_this); }, 0); } }; return func; } };