2014-09-04 35 views
0

有沒有辦法在defineProperty中捕獲Javascript集函數,執行一些邏輯,然後決定是否真的允許調用原始的set函數?有條件地調用/阻止Javascript的defineProperty對象中的setter的調用

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

回答

2

是的,有。你可以用Object.getOwnPropertyDescriptor()得到舊的setter(你在僞代碼中寫成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這樣做纔有效,否則就無法覆蓋它。

+0

令人敬畏的工作@Bergi。我不知道。這非常令人高興,我假設非常容易瞄準我自己的腳。 :) – 2014-09-04 18:28:04

+1

是的,調用這個數據屬性(而不是一個訪問器)會傷害例如:-) – Bergi 2014-09-04 18:33:18

+0

我在IE10上運行此代碼時未將可配置設置爲true並且運行良好。當我在可配置屬性上查找時,我發現它默認爲false。奇怪的。 – 2014-09-04 19:24:46