警告: 通常来讲,你应该尽量避免使用 `watch()`和 `unwatch()` 这两个方法。因为只有 Gecko 实现了这两个方法，并且它们主要是为了在调试方便。另外，使用 watchpoint 对性能有严重的负面影响，在全局对象（如 window）上使用时尤其如此。你可以使用 setters and getters 或者 proxy 代替。参见 Compatibility 了解详情。

`watch()` 方法会监视属性是否被赋值并在赋值时运行相关函数。

## 语法

    obj.watch(prop, handler)

### 参数

`prop`
  想要监视值是否发生变化的指定对象的某个属性的属性名称

`handler`
  当指定的属性发生变化时执行的回调函数

### 返回值

`undefined`.

## 描述

Watches for assignment to a property named `prop` in this object, calling `handler(prop, oldval, newval)` whenever `prop` is set and storing the return value in that property. A watchpoint can filter (or nullify) the value assignment, by returning a modified `newval` (or by returning `oldval`).

If you delete a property for which a watchpoint has been set, that watchpoint does not disappear. If you later recreate the property, the watchpoint is still in effect.

To remove a watchpoint, use the `unwatch()` method. By default, the `watch` method is inherited by every object descended from `Object`.

The JavaScript debugger has functionality similar to that provided by this method, as well as other debugging options. For information on the debugger, see 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`.

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

## 例子

### 使用 `watch` 和 `unwatch`

    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` 来检测一个对象的属性赋值是否是合法的.下例演示了如何确保每个人始终具有一个合法的名字和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("不合法的名字 " + this);
      }
      if (id === "age"  && (newval < 0 || newval > 200)) {
        throw new RangeError("不合法的年龄 " + this);
      }
      return newval;
    }

    will = new Person("Will", 29);
    print(will);   // Will, 29

    try {
      will.name = "";
    } catch (e) {
      //print(e);
      console.log(e);
    }

    try {
      will.age = -4;
    } catch (e) {
      console.log(e);
    }

上面的代码显示结果如下:

    Will, 29
    RangeError: 不合法的名字 Will, 29
    RangeError: 不合法的年龄 Will, 29

## Specifications

Not part of any specifications. Implemented in JavaScript 1.2.

## Browser compatibility

We're converting our compatibility data into a machine-readable JSON format. This compatibility table still uses the old format, because we haven't yet converted the data it contains. Find out how you can help!

- Desktop
- Mobile

Feature | Chrome | Firefox (Gecko) | Internet Explorer | Opera | Safari
--- | --- | --- | --- | --- | ---
Basic support | 未实现 | (Yes) | 未实现 | 未实现 | 未实现

Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile
--- | --- | --- | --- | --- | --- | ---
Basic support | 未实现 | 未实现 | (Yes) | 未实现 | 未实现 | 未实现

## 兼容性提示

- This Polyfill offers `watch` to all ES5 compatible browsers.
- Using a `Proxy` enables you do even deeper changes to how property assignments work.
- Calling `watch()` on the `Document` object throws a `TypeError` since Firefox 23 (bug 903332). This regression has been fixed with Firefox 27.

## 相关链接

- `Object.unwatch()`
- `Object.observe()`