mirror of
https://github.com/fofolee/uTools-Manuals.git
synced 2025-06-12 01:34:04 +08:00
473 lines
34 KiB
HTML
473 lines
34 KiB
HTML
<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-configurable,non-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> |