aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/global_objects/object/defineproperty/index.html
blob: b37662d5ab3abd1474fb1876edc58a3a419d186f (plain)
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
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
---
title: Object.defineProperty()
slug: Web/JavaScript/Reference/Global_Objects/Object/defineProperty
tags:
  - ECMAScript 5
  - JavaScript
  - JavaScript 1.8.5
  - Method
  - Object
  - 对象
  - 方法
translation_of: Web/JavaScript/Reference/Global_Objects/Object/defineProperty
---
<div>{{JSRef}}</div>

<p><code><strong>Object.defineProperty()</strong></code> 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。</p>

<div class="note">
<p><strong>备注:</strong>应当直接在 {{jsxref("Object")}} 构造器对象上调用此方法,而不是在任意一个 <code>Object</code> 类型的实例上调用。</p>
</div>

<div>{{EmbedInteractiveExample("pages/js/object-defineproperty.html")}}</div>



<h2 id="语法">语法</h2>

<pre class="syntaxbox">Object.defineProperty(<var>obj</var>, <var>prop</var>, <var>descriptor</var>)</pre>

<h3 id="参数">参数</h3>

<dl>
 <dt><code><var>obj</var></code></dt>
 <dd>要定义属性的对象。</dd>
 <dt><code><var>prop</var></code></dt>
 <dd>要定义或修改的属性的名称或 {{jsxref("Symbol")}}</dd>
 <dt><code><var>descriptor</var></code></dt>
 <dd>要定义或修改的属性描述符。</dd>
</dl>

<h3 id="返回值">返回值</h3>

<p>被传递给函数的对象。</p>

<div class="note">
<p>在ES6中,由于 Symbol类型的特殊性,用Symbol类型的值来做对象的key与常规的定义或修改不同,而<code>Object.defineProperty</code> 是定义key为Symbol的属性的方法之一。</p>
</div>

<h2 id="描述">描述</h2>

<p>该方法允许精确地添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的,在枚举对象属性时会被枚举到({{jsxref("Statements/for...in", "for...in")}}{{jsxref("Object.keys")}}<a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys"> </a>方法),可以改变这些属性的值,也可以{{jsxref("Operators/delete", "删除")}}这些属性。这个方法允许修改默认的额外选项(或配置)。默认情况下,使用 <code>Object.defineProperty()</code> 添加的属性值是不可修改(immutable)的。</p>

<p>对象里目前存在的属性描述符有两种主要形式:<em>数据描述符</em><em>存取描述符</em><em>数据描述符</em>是一个具有值的属性,该值可以是可写的,也可以是不可写的。<em>存取描述符</em>是由 getter 函数和 setter 函数所描述的属性。一个描述符只能是这两者其中之一;不能同时是两者。</p>

<p>这两种描述符都是对象。它们共享以下可选键值(默认值是指在使用 <code>Object.defineProperty()</code> 定义属性时的默认值):</p>

<dl>
 <dt><code>configurable</code></dt>
 <dd>当且仅当该属性的 <code>configurable</code> 键值为 <code>true</code> 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除。<br>
 <strong>默认为 </strong> <strong><code>false</code></strong></dd>
 <dt><code>enumerable</code></dt>
 <dd>当且仅当该属性的 <code>enumerable</code> 键值为 <code>true</code> 时,该属性才会出现在对象的枚举属性中。<br>
 <strong>默认为 <code>false</code></strong></dd>
</dl>

<p>数据描述符还具有以下可选键值:</p>

<dl>
 <dt><code>value</code></dt>
 <dd>该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。<br>
 <strong>默认为 {{jsxref("undefined")}}</strong></dd>
 <dt><code>writable</code></dt>
 <dd>当且仅当该属性的 <code>writable</code> 键值为 <code>true</code> 时,属性的值,也就是上面的 <code>value</code>,才能被{{jsxref("Operators/Assignment_Operators", "赋值运算符")}}改变。<br>
 <strong>默认为 <code>false</code></strong></dd>
</dl>

<p>存取描述符还具有以下可选键值:</p>

<dl>
 <dt><code>get</code></dt>
 <dd>属性的 getter 函数,如果没有 getter,则为 <code>undefined</code>。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 <code>this</code> 对象(由于继承关系,这里的<code>this</code>并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值。<br>
 <strong>默认为 {{jsxref("undefined")}}</strong></dd>
 <dt><code>set</code></dt>
 <dd>属性的 setter 函数,如果没有 setter,则为 <code>undefined</code>。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 <code>this</code> 对象。<br>
 <strong>默认为 {{jsxref("undefined")}}</strong></dd>
</dl>

<h4 id="描述符默认值汇总">描述符默认值汇总</h4>

<ul>
 <li>拥有布尔值的键 <code>configurable</code><code>enumerable</code><code>writable</code> 的默认值都是 <code>false</code></li>
 <li>属性值和函数的键 <code>value</code><code>get</code><code>set</code> 字段的默认值为 <code>undefined</code></li>
</ul>

<h4 id="描述符可拥有的键值">描述符可拥有的键值</h4>

<dl>
 <dt>
 <table class="standard-table">
  <caption></caption>
  <tbody>
   <tr>
    <td></td>
    <td><code>configurable</code></td>
    <td><code>enumerable</code></td>
    <td><code>value</code></td>
    <td><code>writable</code></td>
    <td><code>get</code></td>
    <td><code>set</code></td>
   </tr>
   <tr>
    <td>数据描述符</td>
    <td>可以</td>
    <td>可以</td>
    <td>可以</td>
    <td>可以</td>
    <td>不可以</td>
    <td>不可以</td>
   </tr>
   <tr>
    <td>存取描述符</td>
    <td>可以</td>
    <td>可以</td>
    <td>不可以</td>
    <td>不可以</td>
    <td>可以</td>
    <td>可以</td>
   </tr>
  </tbody>
 </table>
 </dt>
</dl>

<p>如果一个描述符不具有 <code>value</code><code>writable</code><code>get</code><code>set</code> 中的任意一个键,那么它将被认为是一个数据描述符。如果一个描述符同时拥有 <code>value</code><code>writable</code><code>get</code><code>set</code> 键,则会产生一个异常。</p>

<p>记住,这些选项不一定是自身属性,也要考虑继承来的属性。为了确认保留这些默认值,在设置之前,可能要冻结 {{jsxref("Object.prototype")}},明确指定所有的选项,或者通过 {{jsxref("Object.create", "Object.create(null)")}}{{jsxref("Object.prototype.__proto__", "__proto__")}} 属性指向 {{jsxref("null")}}</p>

<pre class="brush: js">// 使用 __proto__
var obj = {};
var descriptor = Object.create(null); // 没有继承的属性
// 默认没有 enumerable,没有 configurable,没有 writable
descriptor.value = 'static';
Object.defineProperty(obj, 'key', descriptor);

// 显式
Object.defineProperty(obj, "key", {
  enumerable: false,
  configurable: false,
  writable: false,
  value: "static"
});

// 循环使用同一对象
function withValue(value) {
  var d = withValue.d || (
    withValue.d = {
      enumerable: false,
      writable: false,
      configurable: false,
      value: null
    }
  );
  d.value = value;
  return d;
}
// ... 并且 ...
Object.defineProperty(obj, "key", withValue("static"));

// 如果 freeze 可用, 防止后续代码添加或删除对象原型的属性
// (value, get, set, enumerable, writable, configurable)
(Object.freeze||Object)(Object.prototype);</pre>

<h2 id="示例">示例</h2>

<p>如果你想了解如何使用 <code>Object.defineProperty</code> 方法和<em>类二进制标记</em>语法,可以看看这些<a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples" style="line-height: 1.5;">额外示例</a></p>

<h3 id="创建属性">创建属性</h3>

<p>如果对象中不存在指定的属性,<code>Object.defineProperty()</code> 会创建这个属性。当描述符中省略某些字段时,这些字段将使用它们的默认值。</p>

<pre class="brush: js">var o = {}; // 创建一个新对象

// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, "a", {
  value : 37,
  writable : true,
  enumerable : true,
  configurable : true
});

// 对象 o 拥有了属性 a,值为 37

// 在对象中添加一个设置了存取描述符属性的示例
var bValue = 38;
Object.defineProperty(o, "b", {
  // 使用了方法名称缩写(ES2015 特性)
  // 下面两个缩写等价于:
  // get : function() { return bValue; },
  // set : function(newValue) { bValue = newValue; },
  get() { return bValue; },
  set(newValue) { bValue = newValue; },
  enumerable : true,
  configurable : true
});

o.b; // 38
// 对象 o 拥有了属性 b,值为 38
// 现在,除非重新定义 o.b,o.b 的值总是与 bValue 相同

// 数据描述符和存取描述符不能混合使用
Object.defineProperty(o, "conflict", {
  value: 0x9f91102,
  get() { return 0xdeadbeef; }
});
// 抛出错误 TypeError: value appears only in data descriptors, get appears only in accessor descriptors
</pre>

<h3 id="修改属性">修改属性</h3>

<p>如果属性已经存在,<code>Object.defineProperty()</code>将尝试根据描述符中的值以及对象当前的配置来修改这个属性。如果旧描述符将其<code>configurable</code> 属性设置为<code>false</code>,则该属性被认为是“不可配置的”,并且没有属性可以被改变(除了单向改变 writable 为 false)。当属性不可配置时,不能在数据和访问器属性类型之间切换。</p>

<p>当试图改变不可配置属性(除了 <code>value</code><code>writable</code> 属性之外)的值时,会抛出{{jsxref("TypeError")}},除非当前值和新值相同。</p>

<h4 id="Writable_属性">Writable 属性</h4>

<p><code>writable</code> 属性设置为 <code>false</code> 时,该属性被称为“不可写的”。它不能被重新赋值。</p>

<pre class="brush: js">var o = {}; // 创建一个新对象

Object.defineProperty(o, 'a', {
  value: 37,
  writable: false
});

console.log(o.a); // logs 37
o.a = 25; // No error thrown
// (it would throw in strict mode,
// even if the value had been the same)
console.log(o.a); // logs 37. The assignment didn't work.

// strict mode
(function() {
  'use strict';
  var o = {};
  Object.defineProperty(o, 'b', {
    value: 2,
    writable: false
  });
  o.b = 3; // throws TypeError: "b" is read-only
  return o.b; // returns 2 without the line above
}());</pre>

<p>如示例所示,试图写入非可写属性不会改变它,也不会引发错误。</p>

<h4 id="Enumerable_属性">Enumerable 属性</h4>

<p><code>enumerable</code> 定义了对象的属性是否可以在 {{jsxref("Statements/for...in", "for...in")}} 循环和 {{jsxref("Object.keys()")}} 中被枚举。</p>

<pre class="brush: js">var o = {};
Object.defineProperty(o, "a", { value : 1, enumerable: true });
Object.defineProperty(o, "b", { value : 2, enumerable: false });
Object.defineProperty(o, "c", { value : 3 }); // enumerable 默认为 false
o.d = 4; // 如果使用直接赋值的方式创建对象的属性,则 enumerable 为 true
Object.defineProperty(o, Symbol.for('e'), {
  value: 5,
  enumerable: true
});
Object.defineProperty(o, Symbol.for('f'), {
  value: 6,
  enumerable: false
});

for (var i in o) {
  console.log(i);
}
// logs 'a' and 'd' (in undefined order)

Object.keys(o); // ['a', 'd']

o.propertyIsEnumerable('a'); // true
o.propertyIsEnumerable('b'); // false
o.propertyIsEnumerable('c'); // false
o.propertyIsEnumerable('d'); // true
o.propertyIsEnumerable(Symbol.for('e')); // true
o.propertyIsEnumerable(Symbol.for('f')); // false

var p = { ...o }
p.a // 1
p.b // undefined
p.c // undefined
p.d // 4
p[Symbol.for('e')] // 5
p[Symbol.for('f')] // undefined</pre>

<h4 id="Configurable_属性">Configurable 属性</h4>

<p><code>configurable</code> 特性表示对象的属性是否可以被删除,以及除 <code>value</code><code>writable</code> 特性外的其他特性是否可以被修改。</p>

<pre class="brush: js">var o = {};
Object.defineProperty(o, 'a', {
  get() { return 1; },
  configurable: false
});

Object.defineProperty(o, 'a', {
  configurable: true
}); // throws a TypeError
Object.defineProperty(o, 'a', {
  enumerable: true
}); // throws a TypeError
Object.defineProperty(o, 'a', {
  set() {}
}); // throws a TypeError (set was undefined previously)
Object.defineProperty(o, 'a', {
  get() { return 1; }
}); // throws a TypeError
// (even though the new get does exactly the same thing)
Object.defineProperty(o, 'a', {
  value: 12
}); // throws a TypeError // ('value' can be changed when 'configurable' is false but not in this case due to 'get' accessor)

console.log(o.a); // logs 1
delete o.a; // Nothing happens
console.log(o.a); // logs 1</pre>

<p>如果 <code>o.a</code><code>configurable</code> 属性为 <code>true</code>,则不会抛出任何错误,并且,最后,该属性会被删除。</p>

<h3 id="添加多个属性和默认值">添加多个属性和默认值</h3>

<p>考虑特性被赋予的默认特性值非常重要,通常,使用点运算符和 <code>Object.defineProperty()</code> 为对象的属性赋值时,数据描述符中的属性默认值是不同的,如下例所示。</p>

<pre class="brush: js">var o = {};

o.a = 1;
// 等同于:
Object.defineProperty(o, "a", {
  value: 1,
  writable: true,
  configurable: true,
  enumerable: true
});


// 另一方面,
Object.defineProperty(o, "a", { value : 1 });
// 等同于:
Object.defineProperty(o, "a", {
  value: 1,
  writable: false,
  configurable: false,
  enumerable: false
});
</pre>

<h3 id="自定义_Setters_和_Getters">自定义 Setters 和 Getters</h3>

<p>下面的例子展示了如何实现一个自存档对象。当设置<code>temperature</code> 属性时,<code>archive</code> 数组会收到日志条目。</p>

<pre class="brush: js">function Archiver() {
  var temperature = null;
  var archive = [];

  Object.defineProperty(this, 'temperature', {
    get: function() {
      console.log('get!');
      return temperature;
    },
    set: function(value) {
      temperature = value;
      archive.push({ val: temperature });
    }
  });

  this.getArchive = function() { return archive; };
}

var arc = new Archiver();
arc.temperature; // 'get!'
arc.temperature = 11;
arc.temperature = 13;
arc.getArchive(); // [{ val: 11 }, { val: 13 }]</pre>

<p>下面这个例子中,getter 总是会返回一个相同的值。</p>

<pre class="brush: js">var pattern = {
    get: function () {
        return 'I alway return this string,whatever you have assigned';
    },
    set: function () {
        this.myname = 'this is my name string';
    }
};


function TestDefineSetAndGet() {
    Object.defineProperty(this, 'myproperty', pattern);
}


var instance = new TestDefineSetAndGet();
instance.myproperty = 'test';

// 'I alway return this string,whatever you have assigned'
console.log(instance.myproperty);
// 'this is my name string'
console.log(instance.myname);</pre>

<h3 id="继承属性">继承属性</h3>

<p>如果访问者的属性是被继承的,它的 <code>get</code><code>set</code> 方法会在子对象的属性被访问或者修改时被调用。如果这些方法用一个变量存值,该值会被所有对象共享。</p>

<pre class="brush: js">function myclass() {
}

var value;
Object.defineProperty(myclass.prototype, "x", {
  get() {
    return value;
  },
  set(x) {
    value = x;
  }
});

var a = new myclass();
var b = new myclass();
a.x = 1;
console.log(b.x); // 1
</pre>

<p>这可以通过将值存储在另一个属性中解决。在 <code>get</code><code>set</code> 方法中,<code>this</code> 指向某个被访问和修改属性的对象。</p>

<pre class="brush: js">function myclass() {
}

Object.defineProperty(myclass.prototype, "x", {
  get() {
    return this.stored_x;
  },
  set(x) {
    this.stored_x = x;
  }
});

var a = new myclass();
var b = new myclass();
a.x = 1;
console.log(b.x); // undefined</pre>

<p>不像访问者属性,值属性始终在对象自身上设置,而不是一个原型。然而,如果一个不可写的属性被继承,它仍然可以防止修改对象的属性。</p>

<pre class="brush: js">function myclass() {
}

myclass.prototype.x = 1;
Object.defineProperty(myclass.prototype, "y", {
  writable: false,
  value: 1
});

var a = new myclass();
a.x = 2;
console.log(a.x); // 2
console.log(myclass.prototype.x); // 1
a.y = 2; // Ignored, throws in strict mode
console.log(a.y); // 1
console.log(myclass.prototype.y); // 1
</pre>

<h2 id="规范">规范</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">规范</th>
   <th scope="col">状态</th>
   <th scope="col">备注</th>
  </tr>
  <tr>
   <td>{{SpecName('ES5.1', '#sec-15.2.3.6', 'Object.defineProperty')}}</td>
   <td>{{Spec2('ES5.1')}}</td>
   <td>Initial definition. Implemented in JavaScript 1.8.5.</td>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-object.defineproperty', 'Object.defineProperty')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td></td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-object.defineproperty', 'Object.defineProperty')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td></td>
  </tr>
 </tbody>
</table>

<h2 id="浏览器兼容性">浏览器兼容性</h2>



<p>{{Compat("javascript.builtins.Object.defineProperty")}}</p>

<h2 id="兼容性问题">兼容性问题</h2>

<h3 id="重定义数组_Array_对象的_length_属性">重定义数组 <code>Array</code> 对象的 <code>length</code> 属性</h3>

<p>重定义数组的 {{jsxref("Array.length", "length")}} 属性是可能的,但是会受到一般的重定义限制。({{jsxref("Array.length", "length")}} 属性初始为 non-configurable,non-enumerable 以及 writable。对于一个内容不变的数组,改变其 {{jsxref("Array.length", "length")}} 属性的值或者使它变为 non-writable 是可能的。但是改变其可枚举性和可配置性或者当它是 non-writable 时尝试改变它的值或是可写性,这两者都是不允许的。)然而,并不是所有的浏览器都允许 <code>Array.length</code> 的重定义。</p>

<p>在 Firefox 4 至 22 版本中,尝试重定义数组的 length 属性都会抛出 {{jsxref("TypeError")}} 异常。</p>

<p>一些版本的 Chrome 中,<code>Object.defineProperty()</code> 在某些情况下会忽略不同于数组当前{{jsxref("Array.length", "length")}}属性的length值。有些情况下改变可写性并不起作用(也不抛出异常)。同时,比如{{jsxref("Array.prototype.push")}}的一些数组操作方法也不会考虑不可读的length属性。</p>

<p>一些版本的 Safari 中,<code>Object.defineProperty()</code> 在某些情况下会忽略不同于数组当前{{jsxref("Array.length", "length")}}属性的length值。尝试改变可写性的操作会正常执行而不抛出错误,但事实上并未改变属性的可写性。</p>

<p>只在Internet Explorer 9及以后版本和Firefox 23及以后版本中,才完整地正确地支持数组 {{jsxref("Array.length", "length")}} 属性的重新定义。目前不要依赖于重定义数组 {{jsxref("Array.length", "length")}} 属性能够起作用,或在特定情形下起作用。与此同时,即使你能够依赖于它,你也<a href="http://whereswalden.com/2013/08/05/new-in-firefox-23-the-length-property-of-an-array-can-be-made-non-writable-but-you-shouldnt-do-it/">没有合适的理由这样做</a></p>

<h3 id="Internet_Explorer_8_特别备注">Internet Explorer 8 特别备注</h3>

<p>Internet Explorer 8 实现了 <code>Object.defineProperty()</code> 方法,但<a class="external" href="http://msdn.microsoft.com/en-us/library/dd229916%28VS.85%29.aspx">只能在 DOM 对象上使用</a>。 需要注意的一些事情:</p>

<ul>
 <li>尝试在原生对象上使用 <code>Object.defineProperty()</code> 会报错。</li>
 <li>属性特性必须设置一些特定的值。对于数据属性描述符,<code>configurable</code>, <code>enumerable</code><code>writable</code> 属性必须全部设置为 <code>true</code>;对于访问器属性描述符,<code>configurable</code> 必须设置为 <code>true</code><code>enumerable</code> 必须设置为 <code>false</code>。(?) 任何试图提供其他值(?)将导致一个错误抛出。</li>
 <li>重新配置一个属性首先需要删除该属性。如果属性没有删除,就如同重新配置前的尝试。</li>
</ul>

<h3 id="Chrome_37(及以下)特别备注">Chrome 37(及以下)特别备注</h3>

<p>Chrome 37(及以下)有一个 <a href="https://bugs.chromium.org/p/v8/issues/detail?id=3448">bug</a>,使用 <code>writable: false</code> 定义原型 prototype 属性,或者函数时,不会像预期的那样工作。</p>

<h2 id="相关链接">相关链接</h2>

<ul>
 <li><a href="/zh-CN/docs/Enumerability_and_ownership_of_properties">属性的可枚举性和所有权</a></li>
 <li>{{jsxref("Object.defineProperties()")}}</li>
 <li>{{jsxref("Object.propertyIsEnumerable()")}}</li>
 <li>{{jsxref("Object.getOwnPropertyDescriptor()")}}</li>
 <li>{{jsxref("Object.prototype.watch()")}}</li>
 <li>{{jsxref("Object.prototype.unwatch()")}}</li>
 <li>{{jsxref("Operators/get", "get")}}</li>
 <li>{{jsxref("Operators/set", "set")}}</li>
 <li>{{jsxref("Object.create()")}}</li>
 <li><a href="/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples">Additional <code>Object.defineProperty</code> examples</a></li>
 <li>{{jsxref("Reflect.defineProperty()")}}</li>
</ul>