watch

  • 版本网址缩略名: JavaScript/Reference/Global_Objects/Object/watch
  • 版本标题: watch
  • 版本 id: 234057
  • 创建于:
  • 创建者: ziyunfei
  • 是否是当前版本?
  • 评论 4 words added, 14 words removed

修订内容

{{ Non-standard_header() }}

概述

监视一个对象的某个属性是否发生变化,在该属性变化时立即触发指定的回调函数.

Method of Object
Implemented in JavaScript 1.8.6
ECMAScript Edition none

语法

object.watch(prop, handler)

参数

prop
想要监视值是否发生变化的指定对象的某个属性的属性名称
handler
当指定的属性发生变化时执行的回调函数

Description

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 {{ anch("Compatibility") }} for details.

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.

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

Examples

Example: Using watch and unwatch

var o = {p:1};
o.watch("p",
  function (id, oldval, newval) {
    console.log("o." + id + " changed from " + oldval + " to " + newval);
    return newval;
  });

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

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

This script displays the following:

o.p changed from 1 to 2
o.p changed from 2 to 3
o.p changed from undefined to 4

例子: 使用 watch 来验证一个对象的属性

You can use watch to test any assignment to an object's properties. This example ensures that every Person always has a valid name and an age between 0 and 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);
print(will);   // Will, 29

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

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

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

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

兼容性

  • Polyfill 在所有的支持ES5的浏览器上提供了watch方法.
  • Using a Proxy enables you do that even deeper changes to how property assignments work

相关链接

unwatch()

{{ languages( {"en": "en/JavaScript/Reference/Global_Objects/Object/watch","es": "es/Referencia_de_JavaScript_1.5/Objetos_globales/Object/watch", "fr": "fr/R\u00e9f\u00e9rence_de_JavaScript_1.5_Core/Objets_globaux/Object/watch", "ja": "ja/Core_JavaScript_1.5_Reference/Global_Objects/Object/watch", "pl": "pl/Dokumentacja_j\u0119zyka_JavaScript_1.5/Obiekty/Object/watch" } ) }}

修订版来源

<p>{{ Non-standard_header() }}</p>
<h2 name="Summary">概述</h2>
<p>监视一个对象的某个属性是否发生变化,在该属性变化时立即触发指定的回调函数.</p>
<table class="standard-table"> <thead> <tr> <th class="header" colspan="2">Method of <a href="/zh-cn/JavaScript/Reference/Global_Objects/Object" title="zh-cn/JavaScript/Reference/Global_Objects/Object"><code>Object</code></a></th> </tr> </thead> <tbody> <tr> <td>Implemented in</td> <td>JavaScript 1.8.6</td> </tr> <tr> <td>ECMAScript Edition</td> <td>none</td> </tr> </tbody>
</table>
<h2 name="Syntax">语法</h2>
<p><code><em>object</em>.watch(<em>prop</em>, <em>handler</em>) </code></p><h2 name="Parameters">参数</h2>
<dl> <dt><code>prop</code></dt> <dd>想要监视值是否发生变化的指定对象的某个属性的属性名称</dd>
</dl>
<dl> <dt><code>handler</code></dt> <dd>当指定的属性发生变化时执行的回调函数</dd>
</dl><h2 name="Description">Description</h2>
<div class="warning"><strong>Warning:</strong> Generally you should avoid using <code>watch()</code> and <a href="/zh-cn/JavaScript/Reference/Global_Objects/Object/unwatch" title="/zh-cn/JavaScript/Reference/Global_Objects/Object/unwatch"><code>unwatch()</code></a> 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 <a href="/zh-cn/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters" title="https://developer.mozilla.org/zh-cn/Core_JavaScript_1.5_Guide/Working_with_Objects#Defining_getters_and_setters">setters and getters</a> or proxies instead. See {{ anch("Compatibility") }} for details.</div>
<p>Watches for assignment to a property named <code>prop</code> in this object, calling <code>handler(prop, oldval, newval)</code> whenever <code>prop</code> is set and storing the return value in that property. A watchpoint can filter (or nullify) the value assignment, by returning a modified <code>newval</code> (or by returning <code>oldval</code>).</p>
<p>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.</p>
<p>To remove a watchpoint, use the <code><a href="/zh-cn/JavaScript/Reference/Global_Objects/Object/unwatch" title="zh-cn/JavaScript/Reference/Global_Objects/Object/unwatch">unwatch()</a></code> method. By default, the <code>watch</code> method is inherited by every object descended from <code>Object</code>.</p>
<p>The JavaScript debugger has functionality similar to that provided by this method, as well as other debugging options. For information on the debugger, see <a href="/zh-cn/Venkman" title="zh-cn/Venkman">Venkman</a>.</p>
<p>In Firefox, <code>handler</code> is only called from assignments in script, not from native code. For example, <code>window.watch('location', myHandler)</code> will not call <code>myHandler</code> if the user clicks a link to an anchor within the current document. However, <code>window.location += '#myAnchor'</code> will call <code>myHandler</code>.</p>
<div class="note"><strong>Note:</strong> Calling <code>watch()</code> on an object for a specific property overrides and previous handler attached for that property.</div>
<h2 name="Examples">Examples</h2>
<h3 name="Example:_Using_watch_and_unwatch">Example: Using <code>watch</code> and <code>unwatch</code></h3>
<pre class="brush: js">var o = {p:1};
o.watch("p",
  function (id, oldval, newval) {
    console.log("o." + id + " changed from " + oldval + " to " + newval);
    return newval;
  });

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

o.unwatch('p');
o.p = 5;
</pre>
<p>This script displays the following:</p>
<pre class="eval">o.p changed from 1 to 2
o.p changed from 2 to 3
o.p changed from undefined to 4
</pre>
<h3 name="Example:_Using_watch_to_validate_an_object.27s_properties">例子: 使用 <code>watch</code> 来验证一个对象的属性</h3>
<p>You can use <code>watch</code> to test any assignment to an object's properties. This example ensures that every Person always has a valid name and an age between 0 and 200.</p>
<pre class="brush: js">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" &amp;&amp; (!newval || newval.length &gt; 30)) {
    throw new RangeError("invalid name for " + this);
  }
  if (id === "age"  &amp;&amp; (newval &lt; 0 || newval &gt; 200)) {
    throw new RangeError("invalid age for " + this);
  }
  return newval;
}

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

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

try {
  will.age = -4;
} catch (e) {
  print(e);
}
</pre>
<p>上面的代码显示结果如下:</p>
<pre class="eval">Will, 29
RangeError: invalid name for Will, 29
RangeError: invalid age for Will, 29
</pre>
<h2>兼容性</h2>
<ul> <li><span class="external"><a class="link-https" href="https://gist.github.com/384583" title="https://gist.github.com/384583">Polyfill</a> 在所有的支持<code>ES5</code>的浏览器上提供了<code>watch</code>方法.</span></li> <li>Using a <a href="/zh-cn/JavaScript/Reference/Global_Objects/Proxy" title="Proxy">Proxy</a> enables you do that even deeper changes to how property assignments work</li>
</ul><h2 name="See_Also">相关链接</h2>
<p><a href="/zh-cn/JavaScript/Reference/Global_Objects/Object/unwatch" title="zh-cn/JavaScript/Reference/Global_Objects/Object/unwatch">unwatch()</a></p>
<p>{{ languages( {"en": "en/JavaScript/Reference/Global_Objects/Object/watch","es": "es/Referencia_de_JavaScript_1.5/Objetos_globales/Object/watch", "fr": "fr/R\u00e9f\u00e9rence_de_JavaScript_1.5_Core/Objets_globaux/Object/watch", "ja": "ja/Core_JavaScript_1.5_Reference/Global_Objects/Object/watch", "pl": "pl/Dokumentacja_j\u0119zyka_JavaScript_1.5/Obiekty/Object/watch" } ) }}</p>
恢复到这个版本