1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
|
---
title: Object.prototype.watch()
slug: Web/JavaScript/Reference/Global_Objects/Object/watch
translation_of: Archive/Web/JavaScript/Object.watch
---
<div>{{JSRef}}</div>
<div class="warning">
<p><strong>Warning:</strong> Generally you should avoid using <code>watch()</code> and {{jsxref("Object.prototype.unwatch", "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 <code>window</code>. You can usually use <a href="/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters">setters and getters</a> or proxies instead. See {{anch("Browser compatibility")}} for details. Also, do not confuse {{jsxref("Object.prototype.watch", "Object.watch")}} with {{jsxref("Object.prototype.observe", "Object.observe")}}.</p>
</div>
<p>The <code><strong>watch()</strong></code> method watches for a property to be assigned a value and runs a function when that occurs.</p>
<h2 id="語法">語法</h2>
<pre class="syntaxbox"><code><var>obj</var>.watch(<var>prop</var>, <var>handler</var>)</code></pre>
<h3 id="參數">參數</h3>
<dl>
<dt><code>prop</code></dt>
<dd>所需要監聽其值是否改變的物件屬性</dd>
<dt><code>handler</code></dt>
<dd>當監聽的變數其數值變換時所執行的function</dd>
</dl>
<h3 id="回傳值">回傳值</h3>
<p>{{jsxref("undefined")}}.</p>
<h2 id="Description">Description</h2>
<p>Watches for assignment to a property named <code>prop</code> in this object, 呼叫 <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>當你刪掉所監聽的物件屬性,並不會結束針對該物件屬性的監聽。當你重新產生該屬性時,監聽依舊維持作用。</p>
<p>要停止該次監聽, 須使用 {{jsxref("Object.unwatch", "unwatch()")}} 函式. By default, the <code>watch</code> method is inherited by every object descended from {{jsxref("Object")}}.</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="/en-US/docs/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">
<p><strong>Note:</strong> Calling <code>watch()</code> on an object for a specific property overrides any previous handler attached for that property.</p>
</div>
<h2 id="範例">範例</h2>
<h3 id="使用watch_和_unwatch">使用watch 和 unwatch</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>上述程式執行結果:</p>
<pre>o.p changed from 1 to 2
o.p changed from 2 to 3
o.p changed from undefined to 4
</pre>
<h3 id="使用_watch_驗證物件的屬性">使用 <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' && (!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);
console.log(will); // Will, 29
try {
will.name = '';
} catch (e) {
console.log(e);
}
try {
will.age = -4;
} catch (e) {
console.log(e);
}
</pre>
<p>上述程式執行結果:</p>
<pre>Will, 29
RangeError: invalid name for Will, 29
RangeError: invalid age for Will, 29
</pre>
<h2 id="規格">規格</h2>
<p>Not part of any specifications. Implemented in JavaScript 1.2.</p>
<h2 id="瀏覽器相容性">瀏覽器相容性</h2>
<div>{{CompatibilityTable}}</div>
<div id="compat-desktop">
<table class="compat-table">
<tbody>
<tr>
<th>Feature</th>
<th>Chrome</th>
<th>Firefox (Gecko)</th>
<th>Internet Explorer</th>
<th>Opera</th>
<th>Safari</th>
</tr>
<tr>
<td>Basic support</td>
<td>{{CompatNo}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatNo}}</td>
</tr>
</tbody>
</table>
</div>
<div id="compat-mobile">
<table class="compat-table">
<tbody>
<tr>
<th>Feature</th>
<th>Android</th>
<th>Chrome for Android</th>
<th>Firefox Mobile (Gecko)</th>
<th>IE Mobile</th>
<th>Opera Mobile</th>
<th>Safari Mobile</th>
</tr>
<tr>
<td>Basic support</td>
<td>{{CompatNo}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatVersionUnknown}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatNo}}</td>
<td>{{CompatNo}}</td>
</tr>
</tbody>
</table>
</div>
<h2 id="Compatibility_notes">Compatibility notes</h2>
<ul>
<li>This <a class="external link-https" href="https://gist.github.com/384583">Polyfill</a> offers <code>watch</code> to all ES5 compatible browsers.</li>
<li>Using a {{jsxref("Proxy")}} enables you do even deeper changes to how property assignments work.</li>
<li>Calling <code>watch()</code> on the {{domxref("Document")}} object throws a {{jsxref("TypeError")}} since Firefox 23 ({{bug(903332)}}). This regression has been fixed with Firefox 27.</li>
</ul>
<h2 id="參閱">參閱</h2>
<ul>
<li>{{jsxref("Object.unwatch()")}}</li>
<li>{{jsxref("Object.observe()")}} {{obsolete_inline}}</li>
</ul>
|