在Javascript的defineProperty对象中有条件地调用/阻止调用setter

时间:2014-09-04 17:49:50

标签: javascript defineproperty

有没有办法在defineProperty中捕获Javascript set函数,执行一些逻辑然后决定是否实际允许调用原始set函数?

示例

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);
  }
}

1 个答案:

答案 0 :(得分:2)

是的,有。您可以使用Object.getOwnPropertyDescriptor()将旧的二传手(您在伪代码中写为scope._setMyVar = scope.setMyVar;)。

(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"));

当然,这仅在原始属性描述符具有configurable set to true时才有效,否则我们无法覆盖它。