2019-04-21 11:50:48 +08:00

473 lines
34 KiB
HTML
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<article id="wikiArticle">
<div></div>
<p><code><strong>Object.defineProperty()</strong></code> 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。</p>
<h2 id="语法">语法</h2>
<pre><code class="language-javascript"><code>Object.defineProperty(<var>obj</var>, <var>prop</var>, <var>descriptor</var>)</code></code></pre>
<h3 id="Parameters" name="Parameters">参数</h3>
<dl>
<dt><code>obj</code></dt>
<dd>要在其上定义属性的对象。</dd>
<dt><code>prop</code></dt>
<dd>要定义或修改的属性的名称。</dd>
<dt><code>descriptor</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="Description" name="Description">描述</h2>
<p> </p>
<p>该方法允许精确添加或修改对象的属性。通过赋值操作添加的普通属性是可枚举的,能够在属性枚举期间呈现出来(<a href="Reference/Statements/for...in" title="for...in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性语句都会被执行。"><code>for...in</code></a> 或 <a href="Reference/Global_Objects/Object/keys" title="Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。"><code>Object.keys</code></a><a href="/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys" title="JavaScript/Reference/Global_Objects/Object/keys"> </a>方法), 这些属性的值可以被改变,也可以被<a href="Reference/Operators/delete" title="delete 操作符用于删除对象的某个属性;如果没有指向这个属性的引用,那它最终会被释放。">删除</a>。这个方法允许修改默认的额外选项(或配置)。默认情况下,使用 <code>Object.defineProperty()</code> 添加的属性值是不可修改的。</p>
<p> </p>
<h2 id="属性描述符">属性描述符</h2>
<p> </p>
<p>对象里目前存在的属性描述符有两种主要形式:<strong>数据描述符</strong><strong>存取描述符</strong><strong>数据描述符</strong>是一个具有值的属性,该值可能是可写的,也可能不是可写的。<strong>存取描述符</strong>是由getter-setter函数对描述的属性。描述符必须是这两种形式之一不能同时是两者。</p>
<p><strong>数据描述符和存取描述符均具有</strong>以下可选键值:</p>
<dl>
<dt><code>configurable</code></dt>
<dd>当且仅当该属性的 configurable 为 true 时,该属性<code>描述符</code>才能够被改变,同时该属性也能从对应的对象上被删除。<strong>默认为 false</strong></dd>
<dt><code>enumerable</code></dt>
<dd>当且仅当该属性的<code>enumerable</code><code>true</code>时,该属性才能够出现在对象的枚举属性中。<strong>默认为 false</strong></dd>
</dl>
<p><strong>数据描述符同时具有以下可选键值</strong></p>
<dl>
<dt><code>value</code></dt>
<dd>该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。<strong>默认为 <a href="Reference/Global_Objects/undefined" title="undefined是全局对象的一个属性。也就是说它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。"><code>undefined</code></a></strong></dd>
<dt><code>writable</code></dt>
<dd>当且仅当该属性的<code>writable</code><code>true</code>时,<code>value</code>才能被<a href="Reference/Operators/Assignment_Operators" title="赋值运算符assignment operator基于右值right operand的值给左值left operand赋值。">赋值运算符</a>改变。<strong>默认为 <font face="consolas, Liberation Mono, courier, monospace">false</font></strong></dd>
</dl>
<p><strong>存取描述符同时具有以下可选键值</strong></p>
<dl>
<dt><code>get</code></dt>
<dd>一个给属性提供 getter 的方法,如果没有 getter 则为 <code>undefined</code>。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入<code>this</code>对象(由于继承关系,这里的<code>this</code>并不一定是定义该属性的对象)。</dd>
<dd><strong>默认为 <a href="Reference/Global_Objects/undefined" title="undefined是全局对象的一个属性。也就是说它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。"><code>undefined</code></a></strong></dd>
<dt><code>set</code></dt>
<dd>一个给属性提供 setter 的方法,如果没有 setter 则为 <code>undefined</code>。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。</dd>
<dd><strong>默认为 <a href="Reference/Global_Objects/undefined" title="undefined是全局对象的一个属性。也就是说它是全局作用域的一个变量。undefined的最初值就是原始数据类型undefined。"><code>undefined</code></a></strong></dd>
<dt>
<table class="standard-table">
<caption>
<h4 id="描述符可同时具有的键值">描述符可同时具有的键值</h4>
</caption>
<tbody>
<tr>
<td> </td>
<td>configurable</td>
<td>enumerable</td>
<td>value</td>
<td>writable</td>
<td>get</td>
<td>set</td>
</tr>
<tr>
<td>数据描述符</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
</tr>
<tr>
<td>存取描述符</td>
<td>Yes</td>
<td>Yes</td>
<td>No</td>
<td>No</td>
<td>Yes</td>
<td>Yes</td>
</tr>
</tbody>
</table>
<p>如果一个描述符不具有value,writable,get 和 set 任意一个关键字那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。</p>
</dt>
</dl>
<p>记住,这些选项不一定是自身属性,如果是继承来的也要考虑。为了确认保留这些默认值,你可能要在这之前冻结 <a href="Reference/Global_Objects/Object/prototype" title="Object.prototype 属性表示 Object 的原型对象。"><code>Object.prototype</code></a>,明确指定所有的选项,或者通过 <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/create" title="The Object.create() method creates a new object, using an existing object to provide the newly created object's __proto__ . (see browser console for visual evidence.)"><code>Object.create(null)</code></a><a class="new" href="Reference/Global_Objects/Object/__proto__" rel="nofollow" title="此页面仍未被本地化, 期待您的翻译!"><code>__proto__</code></a>属性指向<a href="Reference/Global_Objects/null" title="值 null 特指对象的值未设置。它是 JavaScript 基本类型 之一。"><code>null</code></a></p>
<pre><code class="language-javascript">// 使用 __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);</code></pre>
<h2 id="Creating_a_property" name="Creating_a_property">示例</h2>
<p>如果你想了解如何使用<code>Object.defineProperty</code>方法和类二进制标记语法<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;" title="JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples">这篇文章</a><span style="line-height: 1.5;"></span></p>
<h3 id="Creating_a_property" name="Creating_a_property">创建属性</h3>
<p>如果对象中不存在指定的属性,<span style="font-family: courier new,andale mono,monospace; line-height: 1.5;"><code>Object.defineProperty()</code></span>就创建这个属性。当描述符中省略某些字段时,这些字段将使用它们的默认值。拥有布尔值的字段的默认值都是<span style="font-family: courier new,andale mono,monospace; line-height: 1.5;"><code>false</code></span><code>value</code><code>get</code><code>set</code>字段的默认值为<code>undefined</code>。一个没有<code>get/set/value/writable</code>定义的属性被称为“通用的”,并被“键入”为一个数据描述符。</p>
<pre><code class="language-javascript">var o = {}; // 创建一个新对象
// 在对象中添加一个属性与数据描述符的示例
Object.defineProperty(o, "a", {
  value : 37,
  writable : true,
  enumerable : true,
  configurable : true
});
// 对象o拥有了属性a值为37
// 在对象中添加一个属性与存取描述符的示例
var bValue;
Object.defineProperty(o, "b", {
  get : function(){
  return bValue;
  },
set : function(newValue){
  bValue = newValue;
  },
  enumerable : true,
  configurable : true
});
o.b = 38;
// <span style="font-size: 1rem;">对象o拥有了属性b值为38</span>
// o.b的值现在总是与bValue相同除非重新定义o.b
// 数据描述符和存取描述符不能混合使用
Object.defineProperty(o, "conflict", {
  value: 0x9f91102,
  get: function() {
  return 0xdeadbeef;
  }
});
// throws a TypeError: value appears only in data descriptors, get appears only in accessor descriptors
</code></pre>
<h3 id="Modifying_a_property" name="Modifying_a_property">修改属性</h3>
<p>如果属性已经存在,<code>Object.defineProperty()</code>将尝试根据描述符中的值以及对象当前的配置来修改这个属性。如果旧描述符将其<code>configurable</code> 属性设置为<code>false</code>,则该属性被认为是“不可配置的”,并且没有属性可以被改变(除了单向改变 writable 为 false。当属性不可配置时不能在数据和访问器属性类型之间切换。</p>
<p>当试图改变不可配置属性(除了<code>value</code><code>writable</code> 属性之外)的值时会抛出<a href="Reference/Global_Objects/TypeError" title="TypeError类型错误 对象用来表示值的类型非预期类型时发生的错误。"><code>TypeError</code></a>,除非当前值和新值相同。</p>
<h4 id="Writable_attribute" name="Writable_attribute">Writable 属性</h4>
<p><code>writable</code>属性设置为<code>false</code>时,该属性被称为“不可写”。它不能被重新分配。</p>
<pre><code class="language-javascript">var o = {}; // Creates a new object
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
}());</code></pre>
<p>如示例所示,试图写入非可写属性不会改变它,也不会引发错误。</p>
<h4 id="Enumerable_attribute" name="Enumerable_attribute">Enumerable 特性</h4>
<p> <code>enumerable</code>定义了对象的属性是否可以在 <a href="Reference/Statements/for...in" title="for...in语句以任意顺序遍历一个对象的可枚举属性。对于每个不同的属性语句都会被执行。"><code>for...in</code></a> 循环和 <a href="Reference/Global_Objects/Object/keys" title="Object.keys() 方法会返回一个由一个给定对象的自身可枚举属性组成的数组,数组中属性名的排列顺序和使用 for...in 循环遍历该对象时返回的顺序一致 。"><code>Object.keys()</code></a> 中被枚举。</p>
<pre><code class="language-javascript">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 defaults to false
o.d = 4; // 如果使用直接赋值的方式创建对象的属性则这个属性的enumerable为true
for (var i in o) {
console.log(i);
}
// 打印 'a' 和 'd' (in undefined order)
Object.keys(o); // ["a", "d"]
o.propertyIsEnumerable('a'); // true
o.propertyIsEnumerable('b'); // false
o.propertyIsEnumerable('c'); // false
</code></pre>
<h4 id="Configurable_attribute" name="Configurable_attribute">Configurable 特性</h4>
<p><code>configurable</code>特性表示对象的属性是否可以被删除,以及除<code>value</code><code>writable</code>特性外的其他特性是否可以被修改。</p>
<pre><code class="language-javascript">var o = {};
Object.defineProperty(o, "a", { get : function(){return 1;},
configurable : false } );
// throws a TypeError
Object.defineProperty(o, "a", {configurable : true});
// throws a TypeError
Object.defineProperty(o, "a", {enumerable : true});
// throws a TypeError (set was undefined previously)
Object.defineProperty(o, "a", {set : function(){}});
// throws a TypeError (even though the new get does exactly the same thing)
Object.defineProperty(o, "a", {get : function(){return 1;}});
// throws a TypeError
Object.defineProperty(o, "a", {value : 12});
console.log(o.a); // logs 1
delete o.a; // Nothing happens
console.log(o.a); // logs 1
</code></pre>
<p>如果<code>o.a</code><code>configurable</code>属性为<code>true</code>,则不会抛出任何错误,并且该属性将在最后被删除。</p>
<h3 id="Adding_properties_and_default_values" name="Adding_properties_and_default_values">添加多个属性和默认值</h3>
<p>考虑特性被赋予的默认特性值非常重要,通常,使用点运算符和<code>Object.defineProperty()</code>为对象的属性赋值时,数据描述符中的属性默认值是不同的,如下例所示。</p>
<pre><code class="language-javascript">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
});
</code></pre>
<h3 id="一般的_Setters_和_Getters">一般的 Setters 和 Getters</h3>
<p>下面的例子展示了如何实现一个自存档对象。 当设置<code>temperature</code> 属性时,<code>archive</code> 数组会获取日志条目。</p>
<pre><code class="language-javascript">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 }]</code></pre>
<p></p>
<pre><code class="language-javascript">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);继承属性</code></pre>
<h3 id="继承属性">继承属性</h3>
<p>如果访问者的属性是被继承的,它的 <code>get</code> 和<code>set</code> 方法会在子对象的属性被访问或者修改时被调用。如果这些方法用一个变量存值,该值会被所有对象共享。</p>
<p> </p>
<pre><code class="language-javascript">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</code></pre>
<p>这可以通过将值存储在另一个属性中解决。在 <code>get</code> 和 <code>set</code> 方法中,<code>this</code> 指向某个被访问和修改属性的对象。</p>
<p> </p>
<pre><code class="language-javascript">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</code></pre>
<p>不像访问者属性,值属性始终在对象自身上设置,而不是一个原型。然而,如果一个不可写的属性被继承,它仍然可以防止修改对象的属性。</p>
<p> </p>
<pre><code class="language-javascript">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
</code></pre>
<h2 id="规范" style="margin-bottom: 20px; line-height: 30px;">规范</h2>
<table class="standard-table">
<tbody>
<tr>
<th scope="col">Specification</th>
<th scope="col">Status</th>
<th scope="col">Comment</th>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/5.1/#sec-15.2.3.6" hreflang="en" lang="en" rel="noopener">ECMAScript 5.1 (ECMA-262)<br/><small lang="zh-CN">Object.defineProperty</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td>Initial definition. Implemented in JavaScript 1.8.5.</td>
</tr>
<tr>
<td><a class="external" href="https://www.ecma-international.org/ecma-262/6.0/#sec-object.defineproperty" hreflang="en" lang="en" rel="noopener">ECMAScript 2015 (6th Edition, ECMA-262)<br/><small lang="zh-CN">Object.defineProperty</small></a></td>
<td><span class="spec-Standard">Standard</span></td>
<td> </td>
</tr>
<tr>
<td><a class="external" href="https://tc39.github.io/ecma262/#sec-object.defineproperty" hreflang="en" lang="en" rel="noopener">ECMAScript Latest Draft (ECMA-262)<br/><small lang="zh-CN">Object.defineProperty</small></a></td>
<td><span class="spec-Draft">Draft</span></td>
<td> </td>
</tr>
</tbody>
</table>
<h2 id="浏览器兼容">浏览器兼容</h2>
<div class="hidden">The compatibility table on this page is generated from structured data. If you'd like to contribute to the data, please check out <a class="external" href="https://github.com/mdn/browser-compat-data" rel="noopener">https://github.com/mdn/browser-compat-data</a> and send us a pull request.</div>
<p></p><div class="bc-data"><a class="bc-github-link external" href="https://github.com/mdn/browser-compat-data" rel="noopener">Update compatibility data on GitHub</a><table class="bc-table bc-table-js"><thead><tr class="bc-platforms"><td></td><th class="bc-platform-desktop" colspan="6"><span>Desktop</span></th><th class="bc-platform-mobile" colspan="7"><span>Mobile</span></th><th class="bc-platform-server" colspan="1"><span>Server</span></th></tr><tr class="bc-browsers"><td></td><th class="bc-browser-chrome"><span class="bc-head-txt-label bc-head-icon-chrome">Chrome</span></th><th class="bc-browser-edge"><span class="bc-head-txt-label bc-head-icon-edge">Edge</span></th><th class="bc-browser-firefox"><span class="bc-head-txt-label bc-head-icon-firefox">Firefox</span></th><th class="bc-browser-ie"><span class="bc-head-txt-label bc-head-icon-ie">Internet Explorer</span></th><th class="bc-browser-opera"><span class="bc-head-txt-label bc-head-icon-opera">Opera</span></th><th class="bc-browser-safari"><span class="bc-head-txt-label bc-head-icon-safari">Safari</span></th><th class="bc-browser-webview_android"><span class="bc-head-txt-label bc-head-icon-webview_android">Android webview</span></th><th class="bc-browser-chrome_android"><span class="bc-head-txt-label bc-head-icon-chrome_android">Chrome for Android</span></th><th class="bc-browser-edge_mobile"><span class="bc-head-txt-label bc-head-icon-edge_mobile">Edge Mobile</span></th><th class="bc-browser-firefox_android"><span class="bc-head-txt-label bc-head-icon-firefox_android">Firefox for Android</span></th><th class="bc-browser-opera_android"><span class="bc-head-txt-label bc-head-icon-opera_android">Opera for Android</span></th><th class="bc-browser-safari_ios"><span class="bc-head-txt-label bc-head-icon-safari_ios">Safari on iOS</span></th><th class="bc-browser-samsunginternet_android"><span class="bc-head-txt-label bc-head-icon-samsunginternet_android">Samsung Internet</span></th><th class="bc-browser-nodejs"><span class="bc-head-txt-label bc-head-icon-nodejs">Node.js</span></th></tr></thead><tbody><tr><th scope="row"><code>defineProperty</code></th><td class="bc-supports-yes bc-browser-chrome"><span class="bc-browser-name">Chrome</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
5</td><td class="bc-supports-yes bc-browser-edge"><span class="bc-browser-name">Edge</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
12</td><td class="bc-supports-yes bc-browser-firefox"><span class="bc-browser-name">Firefox</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
4</td><td class="bc-supports-yes bc-browser-ie bc-has-history"><span class="bc-browser-name">IE</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
9<div class="bc-icons"><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> </div><section class="bc-history" id="sect1"><dl><dt class="bc-supports-yes bc-supports"><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
9<div class="bc-icons"><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> </div></dt><dd><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> Also supported in Internet Explorer 8, but only on DOM objects and with some non-standard behaviors.</dd></dl></section></td><td class="bc-supports-yes bc-browser-opera"><span class="bc-browser-name">Opera</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
11.6</td><td class="bc-supports-yes bc-browser-safari bc-has-history"><span class="bc-browser-name">Safari</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
5.1<div class="bc-icons"><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> </div><section class="bc-history" id="sect2"><dl><dt class="bc-supports-yes bc-supports"><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
5.1<div class="bc-icons"><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> </div></dt><dd><abbr class="only-icon" title="See implementation notes"><span>Notes</span><i class="ic-footnote"></i></abbr> Also supported in Safari 5, but not on DOM objects.</dd></dl></section></td><td class="bc-supports-yes bc-browser-webview_android"><span class="bc-browser-name">WebView Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-chrome_android"><span class="bc-browser-name">Chrome Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-edge_mobile"><span class="bc-browser-name">Edge Mobile</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-firefox_android"><span class="bc-browser-name">Firefox Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
4</td><td class="bc-supports-yes bc-browser-opera_android"><span class="bc-browser-name">Opera Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
11.5</td><td class="bc-supports-yes bc-browser-safari_ios"><span class="bc-browser-name">Safari iOS</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-samsunginternet_android"><span class="bc-browser-name">Samsung Internet Android</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td><td class="bc-supports-yes bc-browser-nodejs"><span class="bc-browser-name">nodejs</span><abbr class="bc-level-yes only-icon" title="Full support">
<span>Full support</span>
</abbr>
Yes</td></tr></tbody></table><section class="bc-legend" id="sect3"><h3 class="offscreen" id="Legend">Legend</h3><dl><dt><span class="bc-supports-yes bc-supports">
<abbr class="bc-level bc-level-yes only-icon" title="Full support">
<span>Full support</span>
 
</abbr></span></dt><dd>Full support</dd><dt><abbr class="only-icon" title="See implementation notes."><span>See implementation notes.</span><i class="ic-footnote"></i></abbr></dt><dd>See implementation notes.</dd></dl></section></div><p></p>
<h2 id="Cross-browser_concerns" name="Cross-browser_concerns">兼容性问题</h2>
<h3 id="Redefining_the_length_property_of_an_Array_object" name="Redefining_the_length_property_of_an_Array_object">重定义数组对象的 length 属性</h3>
<p>数组的 <a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标。"><code>length</code></a> 属性重定义是可能的,但是会受到一般的重定义限制。(<a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标。"><code>length</code></a> 属性初始为 non-configurablenon-enumerable 以及 writable。对于一个内容不变的数组改变其 <a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标。"><code>length</code></a> 属性的值或者使它变为 non-writable 是可能的。但是改变其可枚举性和可配置性或者当它是 non-writable 时尝试改变它的值或是可写性,这两者都是不允许的。)然而,并不是所有的浏览器都允许 <code>Array.length</code> 的重定义。</p>
<p>在 Firefox 4 至 22 版本中尝试去重定义数组的 length 属性都会抛出一个 <a href="Reference/Global_Objects/TypeError" title="TypeError类型错误 对象用来表示值的类型非预期类型时发生的错误。"><code>TypeError</code></a> 异常。</p>
<p>有些版本的Chrome中<code>Object.defineProperty()</code> 在某些情况下会忽略不同于数组当前<a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标。"><code>length</code></a>属性的length值。有些情况下改变可写性并不起作用也不抛出异常。同时比如<a href="Reference/Global_Objects/Array/push" title="push() 方法将一个或多个元素添加到数组的末尾,并返回该数组的新长度。"><code>Array.prototype.push</code></a>的一些数组操作方法也不会考虑不可读的length属性。</p>
<p>有些版本的Safari中<code>Object.defineProperty()</code>  在某些情况下会忽略不同于数组当前<a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标。"><code>length</code></a>属性的length值。尝试改变可写性的操作会正常执行而不抛出错误但事实上并未改变属性的可写性。</p>
<p>只在Internet Explorer 9及以后版本和Firefox 23及以后版本中才完整地正确地支持数组<a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标。"><code>length</code></a>属性的重新定义。目前不要依赖于重定义数组<a href="Reference/Global_Objects/Array/length" title="length 是Array的实例属性。返回或设置一个数组中的元素个数。该值是一个无符号 32-bit 整数,并且总是大于数组最高项的下标。"><code>length</code></a> 属性能够起作用,或在特定情形下起作用。与此同时,即使你能够依赖于它,你也<a class="external" 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/" rel="noopener">没有合适的理由这样做</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" rel="noopener">只能在 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>
<h2 id="See_also" name="See_also" style="margin-bottom: 20px; line-height: 30px;">相关链接</h2>
<ul>
<li><a href="https://developer.mozilla.org/en-US/docs/Enumerability_and_ownership_of_properties" title="Enumerability_and_ownership_of_properties">Enumerability and ownership of properties</a></li>
<li><a href="Reference/Global_Objects/Object/defineProperties" title="Object.defineProperties() 方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。"><code>Object.defineProperties()</code></a></li>
<li><a href="Reference/Global_Objects/Object/propertyIsEnumerable" title="propertyIsEnumerable() 方法返回一个布尔值,表示指定的属性是否可枚举。"><code>Object.propertyIsEnumerable()</code></a></li>
<li><a href="Reference/Global_Objects/Object/getOwnPropertyDescriptor" title="Object.getOwnPropertyDescriptor() 方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性)"><code>Object.getOwnPropertyDescriptor()</code></a></li>
<li><a href="Reference/Global_Objects/Object/watch" title="undefined."><code>Object.prototype.watch()</code></a></li>
<li><a href="Reference/Global_Objects/Object/unwatch" title="unwatch() 删除一个 watch() 设置的 watchpoint."><code>Object.prototype.unwatch()</code></a></li>
<li><a class="new" href="Reference/Operators/get" rel="nofollow" title="此页面仍未被本地化, 期待您的翻译!"><code>get</code></a></li>
<li><a class="new" href="Reference/Operators/set" rel="nofollow" title="此页面仍未被本地化, 期待您的翻译!"><code>set</code></a></li>
<li><a href="Reference/Global_Objects/Object/create" title="Object.create()方法创建一个新对象使用现有的对象来提供新创建的对象的__proto__。 (请打开浏览器控制台以查看运行结果。)"><code>Object.create()</code></a></li>
<li><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples">Additional <code>Object.defineProperty</code> examples</a></li>
<li><a href="Reference/Global_Objects/Reflect/defineProperty" title="静态方法 Reflect.defineProperty() 基本等同于 Object.defineProperty() 方法唯一不同是返回 Boolean 值。"><code>Reflect.defineProperty()</code></a></li>
</ul>
</article>