Is there a way to catch a Javascript set function in defineProperty, perform some logic and then decide whether to actually allow the original set function to be invoked?
Example
var scope = {};
scope.myVar = 1;
scope._myVar = scope.myVar;
Object.defineProperty(scope, "myVar", {
get: function(){
return scope._myVar;
},
set: function(val) {
scope._myVar = val;
//Do some other work
}
}
//Now when scope.myVar is changed, its setter is invoked
//I would like to write some code here now that will run even before the
//myVar setter, do some work, and then decide whether to invoke the setter
//or not. If it decides to not invoke the setter, then it will be as
//though the scope.myVar = ... was never called.
//Psuedo-code
scope._setMyVar = scope.setMyVar;
scope.setMyVar = function(val) {
//do some work
var condition = resultOfWorkAbove;
if(condition) {
scope._setMyVar(val);
}
}
Yes, there is. You can get the old setter (what you've written as scope._setMyVar = scope.setMyVar;
in your pseudocode) with Object.getOwnPropertyDescriptor()
.
(function(obj, prop) { // an IEFE for local variables
var desc = Object.getOwnPropertyDescriptor(obj, prop),
oldsetter = desc.set;
desc.set = function(val) {
var condition = … // do some work;
if (condition)
oldsetter.call(this, val);
};
Object.defineProperty(obj, prop, desc);
}(scope, "myVar"));
Of course, this does only work if the original property descriptor had configurable
set to true
, otherwise we cannot overwrite it.