aboutsummaryrefslogtreecommitdiff
path: root/files/zh-cn/web/javascript/reference/global_objects/object/defineproperty
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:40:17 -0500
commit33058f2b292b3a581333bdfb21b8f671898c5060 (patch)
tree51c3e392513ec574331b2d3f85c394445ea803c6 /files/zh-cn/web/javascript/reference/global_objects/object/defineproperty
parent8b66d724f7caf0157093fb09cfec8fbd0c6ad50a (diff)
downloadtranslated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.gz
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.tar.bz2
translated-content-33058f2b292b3a581333bdfb21b8f671898c5060.zip
initial commit
Diffstat (limited to 'files/zh-cn/web/javascript/reference/global_objects/object/defineproperty')
-rw-r--r--files/zh-cn/web/javascript/reference/global_objects/object/defineproperty/index.html545
1 files changed, 545 insertions, 0 deletions
diff --git a/files/zh-cn/web/javascript/reference/global_objects/object/defineproperty/index.html b/files/zh-cn/web/javascript/reference/global_objects/object/defineproperty/index.html
new file mode 100644
index 0000000000..beaca31a6a
--- /dev/null
+++ b/files/zh-cn/web/javascript/reference/global_objects/object/defineproperty/index.html
@@ -0,0 +1,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 notranslate">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> 的默认值都是 <span style="font-family: courier new,andale mono,monospace; line-height: 1.5;"><code>false</code></span>。</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 notranslate">// 使用 __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>语法<span style="line-height: 1.5;">,可以看看</span>这些<a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples" style="line-height: 1.5;">额外示例</a><span style="line-height: 1.5;">。</span></p>
+
+<h3 id="创建属性">创建属性</h3>
+
+<p>如果对象中不存在指定的属性,<span style="font-family: courier new,andale mono,monospace; line-height: 1.5;"><code>Object.defineProperty()</code></span> 会创建这个属性。当描述符中省略某些字段时,这些字段将使用它们的默认值。</p>
+
+<pre class="brush: js notranslate">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 notranslate">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 notranslate">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 notranslate">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 notranslate">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 notranslate">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 notranslate">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 notranslate">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 notranslate">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 notranslate">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>