2012-03-24 3 views
3

get/setの動作を変更するJavaScriptプロパティをラップする機能があります。値である特性のためにObject.createを使用して作成されたJavaScriptプロパティの取得/設定メソッドへのアクセス

、私は、次の操作を行うことができます。

var obj = { 
    myProperty : 0 
}; 

function notifyOfChange(obj, propertyName) { 
    var propertyValue = obj[propertyName]; 
    Object.defineProperty(obj, propertyName, { 
     get : function() { return propertyValue; }, 
     set : function(newValue) { 
      var propertyValue = newValue; 
      console.log("Message from notifyOfChange."); 
     } 
    }); 
}; 

obj.myProperty = 10; // outputs "Message from notifyOfChange." 

しかし、何場合myPropertyにはすでにゲッター/セッターを持っていますか?

var obj = Object.create({}, { 
    myProperty : { 
     get : function() { return this._myProperty; }, 
     set : function(value) { 
      console.log("Message from obj itself."); 
      this._myProperty = value; 
     }, 
     configurable : true 
    } 
}); 

obj.myProperty = 10; // outputs "Message from obj itself"; 

notifyOfChange(obj, "myProperty"); 

obj.myProperty = 10; // outputs "Message from notifyOfChange." 

私はnotifyOfChangeでそれを呼び出すことができるようにmyPropertyに匿名セッターを検出する方法はありますか?

注:どのオブジェクトでもnotifyOfChangeを動作させたいので、 myPropertyセッター用の名前付き関数を使用するだけで動作しません。

答えて

5
function notifyOfPropertyChange(obj, propertyName) { 

    var desc = Object.getOwnPropertyDescriptor(obj, propertyName); 

    if ("value" in desc && desc.writable) { 
     // Value property 

     var propertyValue = obj[propertyName]; 

     Object.defineProperty(obj, propertyName, { 
      get: function() { return propertyValue; }, 
      set: function (newValue) { 
       propertyValue = newValue; 
       console.log("Message from notifyOfChange."); 
      }, 
      configurable: true, 
      enumerable: desc.enumerable 
     }); 

    } else if (desc.set) { 
     // Getter/setter property 

     // Redefine the setter, keep the getter if it exists 
     var originalSet = desc.set.bind(obj); 
     desc.set = function (newValue) { 
      originalSet(newValue); 
      console.log("Message from notifyOfChange."); 
     }; 
     Object.defineProperty(obj, propertyName, desc); 
    } 
} 

Object.getOwnPropertyNamesを使用して、変更するプロパティ名の完全なリストを取得できます。

Object.getOwnPropertyDescriptorの説明については、MDNを参照してください。

+0

if-状態で 'desc.writable'を使うのはなぜですか? – Bergi

+1

書き込み可能なプロパティではない場合は、セッターを与えて書き込み可能にしたいとは思わないでしょう。 – kpozin

+0

OK、私はエラーを投げる前に "通知"メッセージを記録しました:-) – Bergi

関連する問題