Object.prototype.watch

非標準

概要

プロパティに値が代入されるのを監視し、代入された際に関数を実行します。

Objectのメソッド
実装されたバージョン JavaScript 1.8.6
ECMAScript エディション 定義されていない

構文

object.watch(prop, handler)

引数

prop
オブジェクトのプロパティの名前。
handler
呼び出す関数

説明

Warning: Generally you should avoid using watch() and unwatch() when possible. These two methods are implemented only in Gecko, and they're intended primarily for debugging use. In addition, using watchpoints has a serious negative impact on performance, which is especially true when used on global objects, such as window. You can usually use setters and getters or proxies instead. See Compatibility for details.

名前が prop であるオブジェクト中のプロパティへの代入処理を監視し、prop に値がセットされたときには毎回 handler(prop, oldval, newval) を呼び出して、その返り値をプロパティに保存します。ウォッチポイントは修正した newval を返す(あるいは oldval を返す)ことにより、値の代入をフィルタリング(または無効化)することができます。

ウォッチポイントがセットされたプロパティを削除しても、そのウォッチポイントは消滅しません。その後プロパティを再生成しても、ウォッチポイントは効果を持ち続けます。

ウォッチポイントを削除するには、unwatch メソッドを使います。デフォルトで、watch メソッドは Object の子孫であるあらゆるオブジェクトに継承されています。

JavaScript のデバッガは他のデバッグ用オプションと同様に、このメソッドで提供されるものと機能的に似たものを有しています。デバッガについての情報は Venkman をご覧ください。

In Firefox, handler is only called from assignments in script, not from native code. For example, window.watch('location', myHandler) will not call myHandler if the user clicks a link to an anchor within the current document. However, window.location += '#myAnchor' will call myHandler.

Note: Calling watch() on an object for a specific property overrides and previous handler attached for that property.

例: watchunwatch を使う

var o = { p : 1 };

o.watch("p", function (id,oldval,newval) {
  console.log(
    "o." + id + " は " +
    oldval + " から " +
    newval + " に変更されました"
  );

  return newval;
});

o.p = 2;
o.p = 3;
delete o.p;
o.p = 4;

o.unwatch('p');
o.p = 5;

コンソールへの出力は以下の様なものになります。

o.p は 1 から 2 に変更されました
o.p は 2 から 3 に変更されました
o.p は undefined から 4 に変更されました

例: watch を使ってオブジェクトのプロパティの妥当性を評価する

watch を使えば、オブジェクトのプロパティへのあらゆる代入操作を検査することができます。この例はどの Person も常に妥当な名前と 0 から 200 までの年齢を保持することを保証します。

Person = function(name, age) {
  this.watch("age",  Person.prototype._isValidAssignment);
  this.watch("name", Person.prototype._isValidAssignment);
  this.name = name;
  this.age = age;
};

Person.prototype.toString = function() { return this.name + ", " + this.age; };

Person.prototype._isValidAssignment = function(id, oldval, newval) {
  if (id == "name" && (!newval || newval.length > 30)) { throw new RangeError("invalid name for " + this); }
  if (id == "age"  && (newval < 0 || newval > 200))    { throw new RangeError("invalid age  for "  + this); }
  return newval;
};

will = new Person("Will", 29); // --> Will, 29
document.writeln(will);

try {
  will.name = "";  // --> Error "invalid name for Will, 29"
} catch (e) { document.writeln(e); }

try {
  will.age = -4;   // --> Error "invalid age  for Will, 29"
} catch (e) { document.writeln(e); }

このスクリプトは以下のように表示します。

Will, 29
RangeError: invalid name for Will, 29
RangeError: invalid age  for Will, 29

互換性

  • This Polyfill that offers watch to all ES5 compatible browser
  • Using a Proxy enables you do that even deeper changes to how property assignments work

関連情報

Document Tags and Contributors

Contributors to this page: Yuichirou, Potappo, ethertank, Mgjbot
最終更新者: ethertank,