2013-11-22 16 views
13

オブジェクトの(任意の)プロパティにアクセスしたとき、またはアクセスしようとするとキャプチャできますか?Javascript - オブジェクトのプロパティへのアクセスをキャッチ

例:私はFoo

var Foo = (function(){ 
    var self = {}; 
    //... set a few properties 
    return self; 
})(); 

カスタムオブジェクトを作成した

が続いFooに対して何らかのアクションがある - 誰かがbar

Foo.bar 

プロパティにアクセスしようとする方法(試作品がありますおそらく)これをキャプチャするには? barFooで未定義です。定義されていないプロパティへのアクセスを試行しても問題はありません。私の例とは異なり、

Foo.prototype.undefined = function(){ 
    var name = this.name; //name of property they attempted to access (bar) 
    Foo[name] = function(){ 
     //...do something 
    }; 
    return Foo[name]; 
} 

しかし、機能:

barFooに定義されていない場合例えば

、およびFoo.barは何かのように、試みられています。

コンセプト

Foo.* = function(){ 
} 

背景

私はカスタム関数を使用している場合、私は、この関数が呼び出されるたびにために聞くことができます(下記参照)。プロパティへのアクセスが可能かどうかは不思議です。

Foo = function(){}; 
Foo.prototype.call = function(thisArg){ 
    console.log(this, thisArg); 
    return this; 
} 
+1

は不動産 – megawac

+0

@megawacあなたは答えとして、短い例を投稿することができませんか?私は多くのことを必要とせず、正しい方向へのプッシュだけを感じます。 –

+0

できないことを確かめてください。 – SpliFF

答えて

16

これはECMAScript6で可能で、かつ新しいproxy stuffを使用して、Firefoxの上で右ことが可能になりましたでしょう。それまでは、いいえ、私はチェーンに繋ぐ方法がないのではないかと心配しています。

私はしばらくかかりましたが、最終的にこの質問にmy previous answerが見つかりました。プロキシなどのすべての詳細については、その答えを参照してください。ここで

はその答えからプロキシ例です:

var obj = new Proxy({}, { 
    get: function(target, name) { 
     if (!(name in target)) { 
      console.log("Getting non-existant property '" + name + "'"); 
      return undefined; 
     } 
     return target[name]; 
    }, 
    set: function(target, name, value) { 
     if (!(name in target)) { 
      console.log("Setting non-existant property '" + name + "', initial value: " + value); 
     } 
     target[name] = value; 
    } 
}); 

console.log("[before] obj.foo = " + obj.foo); 
obj.foo = "bar"; 
console.log("[after] obj.foo = " + obj.foo); 

Live Copy(現在はFirefoxのみで動作します) |出力Source実行

、:definePropertiesdefineGetterdefineSetterはJavaScriptに新たな付加された状態で

Getting non-existant property 'foo' 
[before] obj.foo = undefined 
Setting non-existant property 'foo', initial value: bar 
[after] obj.foo = bar
+1

私は同意する傾向があり、これは良い情報ですが、私はこれを受け入れる前にしばらくお待ちしています。時々私は黒い魔法のブードゥーの人々が思い付くことに驚いています。 –

+0

@RandyHall:悲しいことに、この場合、私はかなりのブードーは利用できないと確信しています。 :-)上にリンクされた前の答え(元々は2011年のもの)を見てください。 –

+0

あなたは私がこれで行くところを手に入れているようだから... Javascriptはプロパティを見つけようとしますが、それが見つからなければプロトタイプでそのプロパティを見つけようとします(私の理解から) - Foo.prototype.prototypeの作業は何ですか?プロトタイプレイヤーを介してジャバスクリプトのスニッフィングをキャッチし、それに反応することはできますか? –

0

は、あなたがやや似て何かを行うことができます。しかし、オブジェクトの__properties__を隠す真の方法はまだありません。私はあなたがこれを参照することをお勧めしますarticle

var obj = { 
    __properties__: { 
     a: 4 
    } 
} 
Object.defineProperties(obj, { 
    "b": { get: function() { return this.__properties__.a + 1; } }, 
    "c": { get: function (x) { this.__properties__.a = x/2; } } 
}); 

obj.b // 2 
obj.c // .5 

これは、私はあなたが何かをデバッグしようとしているという仮定の下で、これを書こうと思いますどのような環境で

//lame example of a model 
var Model = function(a) { 
    this.__properties__ = {a: a}; 
} 

Model.prototype.get = function(item) { 
    //do processing 
    return this.__properties__[item]; 
} 

Model.prototype.set = function(item, val) { 
    //do processing 
    this.__properties__[item] = val; 
    return this; 
} 

var model = new Model(5); 
model.get("a") // => 5 
+2

良い情報ですが、私が撮影しているものをかなり達成していません。私はそれがアクセスされるようにすべてのプロパティを定義することによって "未定義"を防止しようとしています。オブジェクトの内部で関数を使って、オブジェクトの未定義のプロパティにアクセスしようとするたびに、関数を呼び出す必要があります。 –

3

を動作するはずのモデルの古典的なものです。クラウダーが言ったように、これは新しいブラウザでのみ利用可能です。だから非常にあなたがしたくないコードをテストするのに便利です。しかし、私は生産コードのためにそれを削除します。

Object.defineProperty(Foo, 'bar', { 
    set: function() { 
    debugger; // Here is where I'll take a look in the developer console, figure out what's 
    // gone wrong, and then remove this whole block. 
    } 
}); 

megawacのように見えます。また、機能hereでMozillaのドキュメントを見つけることもできます。

0

他の回答が記載されているように、現時点で未定義のプロパティを傍受する方法はありません。

これでも問題ありませんか?同様に、すでに答え

var myObj = (function() { 
    var props = { 
    foo : 'foo' 
    } 
    return { 
    getProp : function(propName) { return (propName in props) ? props[propName] : 'Nuh-uh!' } 
    } 
}()); 

console.log(myObj.getProp('foo')); // foo 
console.log(myObj.getProp('bar')); // Nuh-uh 
1

は、それだけでECMAScript6でProxyオブジェクトを使用して可能になります。一方、ニーズや全体的なデザインによっては、同様のものを実装することでこれを達成することができます。

など。あなたはプロパティのゲッターとセッターを作成し、「隠す」しない限り、

function WrappingProxy(object, noSuchMember) { 
    if (!this instanceof WrappingProxy) return new WrappingProxy(object); 

    this._object = object; 

    if (noSuchMember) this.noSuchMember = noSuchMember; 
} 

WrappingProxy.prototype = { 
    constructor: WrappingProxy, 

    get: function (propertyName) { 
     var obj = this._object; 

     if (propertyName in obj) return obj[propertyName]; 

     if (this.noSuchMember) this.noSuchMember(propertyName, 'property'); 
    }, 

    set: function (propertyName, value) { 
     return this._object[propertyName] = value; 
    }, 

    invoke: function (functionName) { 
     var obj = this._object, 
      args = Array.prototype.slice.call(arguments, 1); 

     if (functionName in obj) return obj[functionName].apply(obj, args); 

     if (this.noSuchMember) { 
      this.noSuchMember.apply(obj, [functionName, 'function'].concat(args)); 
     } 
    }, 

    object: function() { return this._object }, 

    noSuchMember: null 
}; 

var obj = new WrappingProxy({ 
     testProp: 'test', 
     testFunc: function (v) { 
      return v; 
     } 
    }, 
    //noSuchMember handler 
    function (name, type) { 
     console.log(name, type, arguments[2]); 
    } 
); 

obj.get('testProp'); //test 
obj.get('nonExistingProperty'); //undefined, call noSuchMember 
obj.invoke('testFunc', 'test'); //test 
obj.invoke('nonExistingFunction', 'test'); //undefined, call noSuchMember 

//accesing properties directly on the wrapped object is not monitored 
obj.object().nonExistingProperty; 
+0

私は非常に興味を持っています。これに小さな使用例を追加できますか? –

+0

@RandyHallコードの最後を見ましたか?使用例があります。基本的には、すべてのオブジェクトを 'WrappingProxy'にラップし、メソッド呼び出し(プロパティアクセスを含む)によってすべてのやりとりを実行します。基本的には、これを一貫させたい場合は、オブジェクトのラップされていないバージョンの使用を避けなければなりません。存在しないプロパティをキャッチするための非常に特殊なユースケースがある場合は、そのようなアプローチを使用することは可能かもしれません。 – plalx

+0

ああ、あなたが何をやっているのか分かります。 –

関連する問題