警告: 通常来讲,你应该尽量避免使用 watch()和  setters and getters 或者 proxy 代替。参见 Compatibility 了解详情。

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


obj.watch(prop, handler)






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.


使用 watchunwatch

var o = {p:1};
  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.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) {

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


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


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!
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 bug 903332). This regression has been fixed with Firefox 27.