diff options
Diffstat (limited to 'files/zh-tw/web/javascript/reference/global_objects/object')
13 files changed, 2776 insertions, 0 deletions
diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/assign/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/assign/index.html new file mode 100644 index 0000000000..f4dfca5af7 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/assign/index.html @@ -0,0 +1,249 @@ +--- +title: Object.assign() +slug: Web/JavaScript/Reference/Global_Objects/Object/assign +translation_of: Web/JavaScript/Reference/Global_Objects/Object/assign +--- +<div>{{JSRef}}</div> + +<div><strong><code>Object.assign()</code></strong>被用來複製一個或多個物件自身所有可數的屬性到另一個目標物件。回傳的值為該目標物件。</div> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox notranslate">Object.assign(<var>target</var>, ...<var>sources</var>)</pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>target</code></dt> + <dd>目標物件</dd> + <dt><code>sources</code></dt> + <dd>來源物件</dd> +</dl> + +<h3 id="回傳值">回傳值</h3> + +<p> 合併目標物件及(多個)來源物件所得到的最終物件。</p> + +<h2 id="說明">說明</h2> + +<p>如果在目標物件裡的屬性名稱(key)和來源物件的屬性名稱相同,將會被覆寫。若來源物件之間又有相同的屬性名稱,則後者會將前者覆寫。</p> + +<p><code>Object.assign()</code>只會從來源物件將自身可列舉的屬性複製到目標物件。此函式方法(method) 使用來源物件的<code>[[Get]]</code>事件和目標物件的<code>[[Set]]</code>事件,使它將會執行getters和setters。因此,這邊的指派(<em>assigns</em>)屬性不只是複製或定義新屬性。若在合併包含getters的來源物件時,這個事件可能就不適合用來合併屬性。至於複製屬性的定義(包含其可列舉性)到各屬性,反倒是會用到 {{jsxref("Object.getOwnPropertyDescriptor()")}} 和 {{jsxref("Object.defineProperty()")}} 。</p> + +<p>{{jsxref("String")}} 和 {{jsxref("Symbol")}} 類型的屬性都會被複製。</p> + +<p>若發生錯誤,例如: 當一個屬性不可被寫入時,將會引發 {{jsxref("TypeError")}} 的錯誤,且目標物件剩餘的屬性將不會改變。</p> + +<p>注意: <code>Object.assign()</code> 不會在來源物件屬性的值為{{jsxref("null")}} 或 {{jsxref("undefined")}} 的時候拋出錯誤。</p> + +<h2 id="範例">範例</h2> + +<h3 id="複製物件">複製物件</h3> + +<pre class="brush: js notranslate">var obj = { a: 1 }; +var copy = Object.assign({}, obj); +console.log(copy); // { a: 1 } +</pre> + +<h3 id="Deep_Clone" name="Deep_Clone">警告:非深層複製</h3> + +<p>深層複製(deep clone)需要使用其他的替代方案,因為 <code>Object.assign()</code> 僅複製屬性值。若來源物件的值參照到一個子物件,它只會複製該子物件的參照。</p> + +<pre class="brush: js notranslate">function test() { + let a = { b: {c:4} , d: { e: {f:1}} } + let g = Object.assign({},a) // 淺層 + let h = JSON.parse(JSON.stringify(a)); // 深層 + console.log(g.d) // { e: { f: 1 } } + g.d.e = 32 + console.log('g.d.e set to 32.') // g.d.e set to 32. + console.log(g) // { b: { c: 4 }, d: { e: 32 } } + console.log(a) // { b: { c: 4 }, d: { e: 32 } } + console.log(h) // { b: { c: 4 }, d: { e: { f: 1 } } } + h.d.e = 54 + console.log('h.d.e set to 54.') // h.d.e set to 54. + console.log(g) // { b: { c: 4 }, d: { e: 32 } } + console.log(a) // { b: { c: 4 }, d: { e: 32 } } + console.log(h) // { b: { c: 4 }, d: { e: 54 } } +} +test(); +</pre> + +<h3 id="合併物件">合併物件</h3> + +<pre class="brush: js notranslate">var o1 = { a: 1 }; +var o2 = { b: 2 }; +var o3 = { c: 3 }; + +var obj = Object.assign(o1, o2, o3); +console.log(obj); // { a: 1, b: 2, c: 3 } +console.log(o1); // { a: 1, b: 2, c: 3 }, 目標物件本身也被改變。</pre> + +<h3 id="有相同屬性時合併物件">有相同屬性時合併物件</h3> + +<pre class="brush: js notranslate">var o1 = { a: 1, b: 1, c: 1 }; +var o2 = { b: 2, c: 2 }; +var o3 = { c: 3 }; + +var obj = Object.assign({}, o1, o2, o3); +console.log(obj); // { a: 1, b: 2, c: 3 },屬性c為o3.c的值,最後一個出現的屬性c。</pre> + +<p>所有的屬性會被後方相同屬性名稱的值覆寫。</p> + +<h3 id="複製_Symbol_型別的屬性">複製 Symbol 型別的屬性</h3> + +<pre class="brush: js notranslate">var o1 = { a: 1 }; +var o2 = { [Symbol('foo')]: 2 }; + +var obj = Object.assign({}, o1, o2); +console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox) +Object.getOwnPropertySymbols(obj); // [Symbol(foo)]非不在 +</pre> + +<h3 id="在屬性鏈中的不可列舉屬性不會被複製">在屬性鏈中的不可列舉屬性不會被複製</h3> + +<pre class="brush: js notranslate">var obj = Object.create({ foo: 1 }, { // foo 是 obj 的屬性鏈。 + bar: { + value: 2 // bar 是不可列舉的屬性,因為enumerable預設為false。 + }, + baz: { + value: 3, + enumerable: true // baz 是自身可列舉的屬性。 + } +}); + +var copy = Object.assign({}, obj); +console.log(copy); // { baz: 3 } +</pre> + +<h3 id="原始型別會被包成物件">原始型別會被包成物件</h3> + +<pre class="brush: js notranslate">var v1 = 'abc'; +var v2 = true; +var v3 = 10; +var v4 = Symbol('foo'); + +var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); +// 原始型別會被打包,null和undefined則會被忽略。 +// 注意: 只有打包成物件的字串是可列舉的,即可被複製的。 +console.log(obj); // { "0": "a", "1": "b", "2": "c" } +</pre> + +<h3 id="任何異常將會中斷正進行的複製程序">任何異常將會中斷正進行的複製程序</h3> + +<pre class="brush: js notranslate">var target = Object.defineProperty({}, 'foo', { + value: 1, + writable: false +}); // target.foo 是 read-only (唯讀)屬性 + +Object.assign(target, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 }); +// TypeError: "foo" 是 read-only +// 在指派值給 target.foo 時,異常(Exception)會被拋出。 + +console.log(target.bar); // 2, 第一個來源物件複製成功。 +console.log(target.foo2); // 3, 第二個來源物件的第一個屬性複製成功。 +console.log(target.foo); // 1, 異常在這裡拋出。 +console.log(target.foo3); // undefined, 複製程式已中斷,複製失敗。 +console.log(target.baz); // undefined, 第三個來源物件也不會被複製。 +</pre> + +<h3 id="複製的存取程序">複製的存取程序</h3> + +<pre class="brush: js notranslate">var obj = { + foo: 1, + get bar() { + return 2; + } +}; + +var copy = Object.assign({}, obj); +console.log(copy); +// { foo: 1, bar: 2 }, copy.bar的值,是obj.bar的getter回傳的值。 + +// 這個函式用來複製完整的描述內容。 +function completeAssign(target, ...sources) { + sources.forEach(source => { + let descriptors = Object.keys(source).reduce((descriptors, key) => { + descriptors[key] = Object.getOwnPropertyDescriptor(source, key); + return descriptors; + }, {}); + // Object.assign 預設會複製可列舉的Symbols。 + Object.getOwnPropertySymbols(source).forEach(sym => { + let descriptor = Object.getOwnPropertyDescriptor(source, sym); + if (descriptor.enumerable) { + descriptors[sym] = descriptor; + } + }); + Object.defineProperties(target, descriptors); + }); + return target; +} + +var copy = completeAssign({}, obj); +console.log(copy); +// { foo:1, get bar() { return 2 } } +</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p>{{Glossary("Polyfill","polyfill")}} 不支援Symbol屬性,因為ES5沒有Symbol型別。</p> + +<pre class="brush: js notranslate">if (typeof Object.assign != 'function') { + Object.assign = function (target, varArgs) { // .length of function is 2 + 'use strict'; + if (target == null) { // TypeError if undefined or null + throw new TypeError('Cannot convert undefined or null to object'); + } + + var to = Object(target); + + for (var index = 1; index < arguments.length; index++) { + var nextSource = arguments[index]; + + if (nextSource != null) { // Skip over if undefined or null + for (var nextKey in nextSource) { + // Avoid bugs when hasOwnProperty is shadowed + if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) { + to[nextKey] = nextSource[nextKey]; + } + } + } + } + return to; + }; +} +</pre> + +<h2 id="規格">規格</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>{{SpecName('ES6', '#sec-object.assign', 'Object.assign')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object.assign', 'Object.assign')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{Compat("javascript.builtins.Object.assign")}}</div> + +<div id="compat-desktop"></div> + +<h2 id="參閱">參閱</h2> + +<ul> + <li>{{jsxref("Object.defineProperties()")}}</li> + <li><a href="/en-US/docs/Web/JavaScript/Enumerability_and_ownership_of_properties">Enumerability and ownership of properties</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/create/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/create/index.html new file mode 100644 index 0000000000..f158d36977 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/create/index.html @@ -0,0 +1,258 @@ +--- +title: Object.create() +slug: Web/JavaScript/Reference/Global_Objects/Object/create +translation_of: Web/JavaScript/Reference/Global_Objects/Object/create +--- +<div>{{JSRef}}</div> + +<p><code><strong>Object.create()</strong></code> 指定其原型物件與屬性,創建一個新物件。</p> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox">Object.create(<var>proto</var>[, <var>propertiesObject</var>])</pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>proto</code></dt> + <dd>指定新物件的原型 (prototype) 物件。</dd> + <dt><code>propertiesObject</code></dt> + <dd>選用,為一物件。如有指定且非 {{jsxref("undefined")}},則此參數物件中可列舉出的屬性 (即參數物件自身定義的屬性,並非指原型鏈上的 <code>enumerable</code> 特性 ) 對應其屬性名稱,根據其屬性敘述元 (property descriptors) 加進新創建的物件。這些屬性對應到 {{jsxref("Object.defineProperties()")}} 的第二個參數。</dd> +</dl> + +<h3 id="回傳">回傳</h3> + +<p>具有指定原型物件與屬性的新物件。</p> + +<h3 id="例外">例外</h3> + +<p> 如果 <code>proto</code> 參數不是 {{jsxref("null")}} 或一個物件,將會拋出 {{jsxref("TypeError")}} 例外。</p> + +<h2 id="範例">範例</h2> + +<h3 id="使用_Object.create()_實現類別繼承">使用 <code>Object.create() </code>實現類別繼承</h3> + +<p>下方是如何使用 <code>Object.create()</code> 去實現類別繼承的示範,此為 JavaScript 支援的單一繼承.。</p> + +<pre class="brush: js">// Shape - 父類別 +function Shape() { + this.x = 0; + this.y = 0; +} + +// 父類別的方法 +Shape.prototype.move = function(x, y) { + this.x += x; + this.y += y; + console.info('Shape moved.'); +}; + +// Rectangle - 子類別 +function Rectangle() { + Shape.call(this); // call super constructor. +} + +// 子類別擴展(extends)父類別 +Rectangle.prototype = Object.create(Shape.prototype); +Rectangle.prototype.constructor = Rectangle; + +var rect = new Rectangle(); + +console.log('Is rect an instance of Rectangle?', rect instanceof Rectangle);// true +console.log('Is rect an instance of Shape?', rect instanceof Shape);// true +rect.move(1, 1); // Outputs, 'Shape moved.' +</pre> + +<p>也可像 mixin 繼承多個物件。</p> + +<pre class="brush: js">function MyClass() { + SuperClass.call(this); + OtherSuperClass.call(this); +} + +// 繼承一個父類別 +MyClass.prototype = Object.create(SuperClass.prototype); +// mixin另一個父類別 +Object.assign(MyClass.prototype, OtherSuperClass.prototype); +// 重新指定建構式 +MyClass.prototype.constructor = MyClass; + +MyClass.prototype.myMethod = function() { + // do a thing +}; +</pre> + +<p><a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign">Object.assign</a> 複製 OtherSuperClass 原型上的所有屬性到 MyClass 的原型上,使所有 MyClass 的實例都能使用。Object.assign 為 ES2015 標準且<a href="https://developer.mozilla.org/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/assign#Polyfill">有 polyfill</a>。如需支援較舊的瀏覽器,可使用第三方套件實現如 <a href="https://api.jquery.com/jQuery.extend/">jQuery.extend()</a> 或 <a href="https://lodash.com/docs/#assign">_.assign()</a> 。</p> + +<h3 id="propertiesObject_參數的使用"><code>propertiesObject</code> 參數的使用</h3> + +<pre class="brush: js">var o; + +// 建立以null為原型的物件 +o = Object.create(null); + + +o = {}; +// 等同於: +o = Object.create(Object.prototype); + + +// Example where we create an object with a couple of sample properties. +// (Note that the second parameter maps keys to *property descriptors*.) +o = Object.create(Object.prototype, { + // foo 為數值屬性 + foo: { writable: true, configurable: true, value: 'hello' }, + // bar 為 getter-and-setter 訪問屬性 + bar: { + configurable: false, + get: function() { return 10; }, + set: function(value) { console.log('Setting `o.bar` to', value); } +/* with ES5 Accessors our code can look like this + get function() { return 10; }, + set function(value) { console.log('setting `o.bar` to', value); } */ + } +}); + + +function Constructor() {} +o = new Constructor(); +// 等同於: +o = Object.create(Constructor.prototype); +// Of course, if there is actual initialization code in the +// Constructor function, the Object.create() cannot reflect it + + +// 創建一個新物件,指定原型是全新的空物件,並加入值為 42 的屬性'p' +o = Object.create({}, { p: { value: 42 } }); + +// 屬性敘述元 writable, enumerable , configurable 未定義,預設皆為 false +o.p = 24; +o.p; +// 42 + +o.q = 12; +for (var prop in o) { + console.log(prop); +} +// 'q' + +delete o.p; +// false + +// to specify an ES3 property +o2 = Object.create({}, { + p: { + value: 42, + writable: true, + enumerable: true, + configurable: true + } +}); +</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p>此 polyfill 涵蓋了主要的使用情境:指定一個原型創建一個新的物件,第二個參數為選用。</p> + +<p>要注意的是在 ES5 的<code>Object.create</code>中, <code>[[Prototype]]</code> 可以為 <code>null</code>,但在ECMAScript 5 以前的版本,polyfill 會因為繼承限制( limitation inherent )而不支援此情形。</p> + +<pre><code>if (typeof Object.create !== "function") { + Object.create = function (proto, propertiesObject) { + if (!(proto === null || typeof proto === "object" || typeof proto === "function")) { + throw TypeError('Argument must be an object, or null'); + } + var temp = new Object(); + temp.__proto__ = proto; + if(typeof propertiesObject === "object") + Object.defineProperties(temp, propertiesObject); + return temp; + }; +}</code></pre> + +<h2 id="規範">規範</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>{{SpecName('ES5.1', '#sec-15.2.3.5', 'Object.create')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.8.5.</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-object.create', 'Object.create')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object.create', 'Object.create')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatChrome("5")}}</td> + <td>{{CompatGeckoDesktop("2")}}</td> + <td>{{CompatIE("9")}}</td> + <td>{{CompatOpera("11.60")}}</td> + <td>{{CompatSafari("5")}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatGeckoDesktop("2")}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatOperaMobile("11.5")}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="參閱">參閱</h2> + +<ul> + <li>{{jsxref("Object.defineProperty()")}}</li> + <li>{{jsxref("Object.defineProperties()")}}</li> + <li>{{jsxref("Object.prototype.isPrototypeOf()")}}</li> + <li>John Resig's post on <a href="http://ejohn.org/blog/objectgetprototypeof/">getPrototypeOf()</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/defineproperties/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/defineproperties/index.html new file mode 100644 index 0000000000..fc87ca0317 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/defineproperties/index.html @@ -0,0 +1,224 @@ +--- +title: Object.defineProperties() +slug: Web/JavaScript/Reference/Global_Objects/Object/defineProperties +translation_of: Web/JavaScript/Reference/Global_Objects/Object/defineProperties +--- +<div>{{JSRef}}</div> + +<p><code><strong>Object.defineProperties()</strong></code> 函式可定義新的或是修改已存在的物件屬性,並回傳修改後的物件。</p> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox"><code>Object.defineProperties(<var>obj</var>, <var>props</var>)</code></pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>obj</code></dt> + <dd>The object on which to define or modify properties.</dd> + <dt><code>props</code></dt> + <dd>An object whose own enumerable properties constitute descriptors for the properties to be defined or modified. Property descriptors present in objects come in two main flavors: data descriptors and accessor descriptors (see {{jsxref("Object.defineProperty()")}} for more details). Descriptors have the following keys:</dd> + <dd> + <dl> + <dt><code>configurable</code></dt> + <dd><code>true</code> if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object.<br> + <strong>預設為 <code>false</code>.</strong></dd> + <dt><code>enumerable</code></dt> + <dd><code>若該屬性設為 true,則該屬性可被物件所列舉。</code><br> + <strong>預設為 <code>false</code>.</strong></dd> + </dl> + + <dl> + <dt><code>value</code></dt> + <dd>The value associated with the property. Can be any valid JavaScript value (number, object, function, etc).<br> + <strong>預設為 {{jsxref("undefined")}}.</strong></dd> + <dt><code>writable</code></dt> + <dd><code>若該屬性為 true</code>,則該屬性可透過{{jsxref("Operators/Assignment_Operators", "賦予運算子", "", 1)}}所改變<br> + <strong>預設為 <code>false</code>.</strong></dd> + </dl> + + <dl> + <dt><code>get</code></dt> + <dd>A function which serves as a getter for the property, or {{jsxref("undefined")}} if there is no getter. The function return will be used as the value of property.<br> + <strong>預設為 {{jsxref("undefined")}}.</strong></dd> + <dt><code>set</code></dt> + <dd>A function which serves as a setter for the property, or {{jsxref("undefined")}} if there is no setter. The function will receive as only argument the new value being assigned to the property.<br> + <strong>預設為 {{jsxref("undefined")}}.</strong></dd> + </dl> + </dd> +</dl> + +<h3 id="回傳值">回傳值</h3> + +<p>The object that was passed to the function.</p> + +<h2 id="描述">描述</h2> + +<p><code>Object.defineProperties</code>, in essence, defines all properties corresponding to the enumerable own properties of <code>props</code> on the object <code>obj</code> object.</p> + +<h2 id="範例">範例</h2> + +<pre class="brush: js">var obj = {}; +Object.defineProperties(obj, { + 'property1': { + value: true, + writable: true + }, + 'property2': { + value: 'Hello', + writable: false + } + // etc. etc. +}); +</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p>Assuming a pristine execution environment with all names and properties referring to their initial values, <code>Object.defineProperties</code> is almost completely equivalent (note the comment in <code>isCallable</code>) to the following reimplementation in JavaScript:</p> + +<pre class="brush: js;highlight:[8]">function defineProperties(obj, properties) { + function convertToDescriptor(desc) { + function hasProperty(obj, prop) { + return Object.prototype.hasOwnProperty.call(obj, prop); + } + + function isCallable(v) { + // NB: modify as necessary if other values than functions are callable. + return typeof v === 'function'; + } + + if (typeof desc !== 'object' || desc === null) + throw new TypeError('bad desc'); + + var d = {}; + + if (hasProperty(desc, 'enumerable')) + d.enumerable = !!desc.enumerable; + if (hasProperty(desc, 'configurable')) + d.configurable = !!desc.configurable; + if (hasProperty(desc, 'value')) + d.value = desc.value; + if (hasProperty(desc, 'writable')) + d.writable = !!desc.writable; + if (hasProperty(desc, 'get')) { + var g = desc.get; + + if (!isCallable(g) && typeof g !== 'undefined') + throw new TypeError('bad get'); + d.get = g; + } + if (hasProperty(desc, 'set')) { + var s = desc.set; + if (!isCallable(s) && typeof s !== 'undefined') + throw new TypeError('bad set'); + d.set = s; + } + + if (('get' in d || 'set' in d) && ('value' in d || 'writable' in d)) + throw new TypeError('identity-confused descriptor'); + + return d; + } + + if (typeof obj !== 'object' || obj === null) + throw new TypeError('bad obj'); + + properties = Object(properties); + + var keys = Object.keys(properties); + var descs = []; + + for (var i = 0; i < keys.length; i++) + descs.push([keys[i], convertToDescriptor(properties[keys[i]])]); + + for (var i = 0; i < descs.length; i++) + Object.defineProperty(obj, descs[i][0], descs[i][1]); + + return obj; +} +</pre> + +<h2 id="規格">規格</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</th> + <th scope="col">註記</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.2.3.7', 'Object.defineProperties')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.8.5</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-object.defineproperties', 'Object.defineProperties')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object.defineproperties', 'Object.defineProperties')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Firefox (Gecko)</th> + <th>Chrome</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatGeckoDesktop("2")}}</td> + <td>{{CompatChrome("5")}}</td> + <td>{{CompatIE("9")}}</td> + <td>{{CompatOpera("11.60")}}</td> + <td>{{CompatSafari("5")}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Firefox Mobile (Gecko)</th> + <th>Android</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatGeckoMobile("2")}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatOperaMobile("11.5")}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="參閱">參閱</h2> + +<ul> + <li>{{jsxref("Object.defineProperty()")}}</li> + <li>{{jsxref("Object.keys()")}}</li> + <li><a href="/en-US/docs/Enumerability_and_ownership_of_properties">Enumerability and ownership of properties</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/defineproperty/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/defineproperty/index.html new file mode 100644 index 0000000000..cf83590181 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/defineproperty/index.html @@ -0,0 +1,380 @@ +--- +title: Object.defineProperty() +slug: Web/JavaScript/Reference/Global_Objects/Object/defineProperty +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")}} 呼叫建構子(constructor),而不是 <code>Object</code> 型別的實例。</p> +</div> + +<div>{{EmbedInteractiveExample("pages/js/object-defineproperty.html")}}</div> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox"><code>Object.defineProperty(<var>obj</var>, <var>prop</var>, <var>descriptor</var>)</code></pre> + +<h3 id="參數">參數</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> + +<h2 id="描述">描述</h2> + +<p>這個函式可以用來增加或修改物件中的屬性定義。在物件建立屬性後,這些屬性同時有被設定預設的設定,才能讓這些屬性被列舉、改變和刪除。而這個函式可以用來改變這些預設的設定。根據預設,被加到物件且使用<code>Object.defineProperty()</code>的值都是{{glossary("Immutable")}}。</p> + +<p>物件內的屬性描述器(Property descriptor)主要有兩種:資料描述器(data descriptor)與訪問描述器(accessor descriptor)。<dfn>資料描述器</dfn>(data descriptor)是可以選擇能否覆寫的屬性。<dfn>訪問描述器</dfn>(accessor descriptor) is a property described by a getter-setter pair of functions. A descriptor must be one of these two flavors; it cannot be both.</p> + +<p>data 和 accessor descriptors 皆為物件,兩者共享下面提及的 key:</p> + +<dl> + <dt><code>configurable</code></dt> + <dd><code>true</code> 則若且唯若此屬性則將可改變或刪除自相應物件。<br> + <strong>預設為 <code>false</code></strong></dd> + <dt><code>enumerable</code></dt> + <dd><code>true</code> 如果且唯若相應物件被列舉,將會列舉此屬性。<br> + <strong>預設為 <code>false</code></strong></dd> +</dl> + +<p>一個 data descriptor 還有以下可選的 key:</p> + +<dl> + <dt><code>value</code></dt> + <dd>The value associated with the property. Can be any valid JavaScript value (number, object, function, etc).<br> + <strong>預設 {{jsxref("undefined")}}.</strong></dd> + <dt><code>writable</code></dt> + <dd><code>true</code> 則該物件屬性可透過{{jsxref("Operators/Assignment_Operators", "賦予運算子", "", 1)}}改變其值。<br> + <strong>預設 <code>false</code></strong></dd> +</dl> + +<p>一個 accessor descriptor 也擁有下述之 optional keys:</p> + +<dl> + <dt><code>get</code></dt> + <dd>作為 getter 形式,為屬性存在的函式,如果沒有 getter 的話則回傳 {{jsxref("undefined")}}。函式回傳將用於屬性值。<br> + <strong>預設 {{jsxref("undefined")}}</strong></dd> + <dt><code>set</code></dt> + <dd>作為 setter 形式,為屬性存在的函式,如果沒有 setter 的話則回傳 {{jsxref("undefined")}}。 The function will receive as only argument the new value being assigned to the property.<br> + <strong>預設 {{jsxref("undefined")}}</strong></dd> +</dl> + +<p>請注意,這些選項並不一定要是 descriptor 屬性,由原型鍊(prototype chain)繼承的屬性,也會被考慮到。要確保需要凍結(freeze)的 {{jsxref("Object.prototype")}} upfront 預設能被保存,請明確指定所有選項,或把 {{jsxref("Object.prototype.__proto__", "__proto__")}} 屬性指向 {{jsxref("null")}}。</p> + +<pre class="brush: js">// using __proto__ +var obj = {}; +Object.defineProperty(obj, 'key', { + __proto__: null, // no inherited properties + value: 'static' // not enumerable + // not configurable + // not writable + // as defaults +}); + +// being explicit +Object.defineProperty(obj, 'key', { + enumerable: false, + configurable: false, + writable: false, + value: 'static' +}); + +// recycling same object +function withValue(value) { + var d = withValue.d || ( + withValue.d = { + enumerable: false, + writable: false, + configurable: false, + value: null + } + ); + d.value = value; + return d; +} +// ... and ... +Object.defineProperty(obj, 'key', withValue('static')); + +// if freeze is available, prevents adding or +// removing the object prototype properties +// (value, get, set, enumerable, writable, configurable) +(Object.freeze || Object)(Object.prototype); +</pre> + +<h2 id="範例">範例</h2> + +<p>If you want to see how to use the <code>Object.defineProperty</code> method with a <em>binary-flags-like</em> syntax, see <a href="/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples">additional examples</a>.</p> + +<h3 id="建立屬性">建立屬性</h3> + +<p>When the property specified doesn't exist in the object, <code>Object.defineProperty()</code> creates a new property as described. Fields may be omitted from the descriptor, and default values for those fields are imputed. All of the Boolean-valued fields default to <code>false</code>. The <code>value</code>, <code>get</code>, and <code>set</code> fields default to {{jsxref("undefined")}}. A property which is defined without <code>get</code>/<code>set</code>/<code>value</code>/<code>writable</code> is called “generic” and is “typed” as a data descriptor.</p> + +<pre class="brush: js">var o = {}; // Creates a new object + +// Example of an object property added with defineProperty with a data property descriptor +Object.defineProperty(o, 'a', { + value: 37, + writable: true, + enumerable: true, + configurable: true +}); +// 'a' property exists in the o object and its value is 37 + +// Example of an object property added with defineProperty with an accessor property descriptor +var bValue = 38; +Object.defineProperty(o, 'b', { + get: function() { return bValue; }, + set: function(newValue) { bValue = newValue; }, + enumerable: true, + configurable: true +}); +o.b; // 38 +// 'b' property exists in the o object and its value is 38 +// The value of o.b is now always identical to bValue, unless o.b is redefined + +// You cannot try to mix both: +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 +</pre> + +<h3 id="修改屬性">修改屬性</h3> + +<p>如果該屬性已經存在, <code>Object.defineProperty()</code> 將會根據描述符內的值和物件當前的 configuration 來修改屬性。 如果舊的描述符之 <code>configurable</code> 的特徵為 false (屬性為 “non-configurable”), 那除了 <code>writable</code> 之外的特徵都將無法修改。 在這個情況,也不可能在 data 和 accessor 屬性類型中來回切換。</p> + +<p>如果有一個屬性是 non-configurable, 那它的 <code>writable</code> 特徵只能被改變為 <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">false</span></font>.</p> + +<p>若嘗試改變 non-configurable property attributes,將會丟出一個 {{jsxref("TypeError")}},除非當前之值與新值相同。</p> + +<h4 id="Writable_attribute">Writable attribute</h4> + +<p>當 <code>writable</code> 屬性特徵被設為 <code>false</code>, 此屬性為 “non-writable”. 它將無法被重新賦值。</p> + +<pre class="brush: js">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. +</pre> + +<p>As seen in the example, trying to write into the non-writable property doesn't change it but doesn't throw an error either.</p> + +<h4 id="可列舉_attribute">可列舉 attribute</h4> + +<p>The <code>enumerable</code> property attribute defines whether the property shows up in a {{jsxref("Statements/for...in", "for...in")}} loop and {{jsxref("Object.keys()")}} or not.</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 defaults to false +o.d = 4; // enumerable defaults to true when creating a property by setting it + +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 +</pre> + +<h4 id="可設定_attribute">可設定 attribute</h4> + +<p>The <code>configurable</code> attribute controls at the same time whether the property can be deleted from the object and whether its attributes (other than <code>writable</code>) can be changed.</p> + +<pre class="brush: js">var o = {}; +Object.defineProperty(o, 'a', { + get: function() { 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: function() {} }); // throws a TypeError (set was undefined previously) +Object.defineProperty(o, 'a', { get: function() { return 1; } }); // throws a TypeError (even though the new get does exactly the same thing) +Object.defineProperty(o, 'a', { value: 12 }); // throws a TypeError + +console.log(o.a); // logs 1 +delete o.a; // Nothing happens +console.log(o.a); // logs 1 +</pre> + +<p>If the <code>configurable</code> attribute of <code>o.a</code> had been <code>true</code>, none of the errors would be thrown and the property would be deleted at the end.</p> + +<h3 id="新增多個屬性及賦予初始值">新增多個屬性及賦予初始值</h3> + +<p>It's important to consider the way default values of attributes are applied. There is often a difference between simply using dot notation to assign a value and using <code>Object.defineProperty()</code>, as shown in the example below.</p> + +<pre class="brush: js">var o = {}; + +o.a = 1; +// is equivalent to: +Object.defineProperty(o, 'a', { + value: 1, + writable: true, + configurable: true, + enumerable: true +}); + + +// On the other hand, +Object.defineProperty(o, 'a', { value: 1 }); +// is equivalent to: +Object.defineProperty(o, 'a', { + value: 1, + writable: false, + configurable: false, + enumerable: false +}); +</pre> + +<h3 id="Custom_Setters_and_Getters">Custom Setters and Getters</h3> + +<p>Example below shows how to implement a self-archiving object. When <code>temperature</code> property is set, the <code>archive</code> array gets a log entry.</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>or</p> + +<pre class="brush: js">var pattern = { + get: function () { + return 'I always 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'; +console.log(instance.myproperty); // I always return this string, whatever you have assigned + +console.log(instance.myname); // this is my name string + +</pre> + +<h2 id="規格">規格</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Specification</th> + <th scope="col">Status</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> + +<div> + + +<p>{{Compat("javascript.builtins.Object.defineProperty")}}</p> +</div> + +<h2 id="Compatibility_notes">Compatibility notes</h2> + +<h3 id="Redefining_the_length_property_of_an_Array_object">Redefining the <code>length</code> property of an <code>Array</code> object</h3> + +<p>It is possible to redefine the {{jsxref("Array.length", "length")}} property of arrays, subject to the usual redefinition restrictions. (The {{jsxref("Array.length", "length")}} property is initially non-configurable, non-enumerable, and writable. Thus on an unaltered array, it's possible to change the {{jsxref("Array.length", "length")}} property's value or to make it non-writable. It is not allowed to change its enumerability or configurability, or if it is non-writable to change its value or writability.) However, not all browsers permit this redefinition.</p> + +<p>Firefox 4 through 22 will throw a {{jsxref("TypeError")}} on any attempt whatsoever (whether permitted or not) to redefine the {{jsxref("Array.length", "length")}} property of an array.</p> + +<p>Versions of Chrome which implement <code>Object.defineProperty()</code> in some circumstances ignore a length value different from the array's current {{jsxref("Array.length", "length")}} property. In some circumstances changing writability seems to silently not work (and not throw an exception). Also, relatedly, some array-mutating methods like {{jsxref("Array.prototype.push")}} don't respect a non-writable length.</p> + +<p>Versions of Safari which implement <code>Object.defineProperty()</code> ignore a <code>length</code> value different from the array's current {{jsxref("Array.length", "length")}} property, and attempts to change writability execute without error but do not actually change the property's writability.</p> + +<p>Only Internet Explorer 9 and later, and Firefox 23 and later, appear to fully and correctly implement redefinition of the {{jsxref("Array.length", "length")}} property of arrays. For now, don't rely on redefining the {{jsxref("Array.length", "length")}} property of an array to either work, or to work in a particular manner. And even when you <em>can</em> rely on it, <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/">there's really no good reason to do so</a>.</p> + +<h3 id="Internet_Explorer_8_specific_notes">Internet Explorer 8 specific notes</h3> + +<p>Internet Explorer 8 implemented a <code>Object.defineProperty()</code> method that could <a class="external" href="https://msdn.microsoft.com/en-us/library/dd229916%28VS.85%29.aspx">only be used on DOM objects</a>. A few things need to be noted:</p> + +<ul> + <li>Trying to use <code>Object.defineProperty()</code> on native objects throws an error.</li> + <li>Property attributes must be set to some values. The <code>configurable</code>, <code>enumerable</code> and <code>writable</code> attributes should all be set to <code>true</code> for data descriptor and <code>true</code> for <code>configurable</code>, <code>false</code> for <code>enumerable</code> for accessor descriptor.(?) Any attempt to provide other value(?) will result in an error being thrown.</li> + <li>Reconfiguring a property requires first deleting the property. If the property isn't deleted, it stays as it was before the reconfiguration attempt.</li> +</ul> + +<h2 id="參閱">參閱</h2> + +<ul> + <li><a href="/zh-TW/docs/Enumerability_and_ownership_of_properties">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-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/defineProperty/Additional_examples">Additional <code>Object.defineProperty</code> examples</a></li> + <li>{{jsxref("Reflect.defineProperty()")}}</li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/freeze/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/freeze/index.html new file mode 100644 index 0000000000..0c26b9f308 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/freeze/index.html @@ -0,0 +1,198 @@ +--- +title: Object.freeze() +slug: Web/JavaScript/Reference/Global_Objects/Object/freeze +translation_of: Web/JavaScript/Reference/Global_Objects/Object/freeze +--- +<div>{{JSRef}}</div> + +<p> </p> + +<p><code><strong>Object.freeze()</strong></code> 顧名思義是用來「凍結」一個物件的: 也就是防止物件新增屬性; 防止物件既有的屬性被刪除; 防止物件原本的屬性, 還有屬性的可列舉性, 可設定性, 可寫性被改動; 同時它也防止物件的原型被改變。此方法回傳一個凍結狀態的物件。</p> + +<div>{{EmbedInteractiveExample("pages/js/object-freeze.html")}}</div> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox"><code>Object.freeze(<var>obj</var>)</code></pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>obj</code></dt> + <dd>要被凍結的物件</dd> +</dl> + +<h3 id="回傳值">回傳值</h3> + +<p>被凍結的物件</p> + +<h2 id="描述">描述</h2> + +<p>一個被凍結的物件無法被新增或刪除屬性。任何想要改動的嘗試都會失敗, 要不沈默地失敗, 就是丟出一個 {{jsxref("TypeError")}} 例外 (此例外最常出現在 {{jsxref("Strict_mode", "strict mode", "", 1)}})</p> + +<p>資料屬性無法被改變。訪問者方法 - setters 也一樣不能改變資料屬性 (雖然它會給你可以改變資料值的假象)。注意! 如果資料屬性是物件的話,該物件的值是可以被改變的,除非它們也被凍結。一個陣列同樣可以被凍結 (因為它也是一個物件),被凍結後它的元素內容就不能被改變,也不能新增或刪除元素。</p> + +<h2 id="範例">範例</h2> + +<h3 id="凍結物件">凍結物件</h3> + +<pre class="brush: js">var obj = { + prop: function() {}, + foo: 'bar' +}; + +// 新的屬性可以被新增,原本的屬性可以被改變或刪除 +obj.foo = 'baz'; +obj.lumpy = 'woof'; +delete obj.prop; + +// 回傳的物件跟原本傳入的物件是同一個,所以不需要記住回傳值 +// 也可以凍結一個物件 +var o = Object.freeze(obj); + +o === obj; // true +Object.isFrozen(obj); // === true + +// 現在任何改動都會失敗 +obj.foo = 'quux'; // 什麼事也不會發生 +// 屬性無法被新增 +obj.quaxxor = 'the friendly duck'; + +// 在嚴格模式中,如方才的嘗試都會丟出 TypeError +function fail(){ + 'use strict'; + obj.foo = 'sparky'; // 丟出 TypeError + delete obj.foo; // 丟出 TypeError + delete obj.quaxxor; // 回傳 true 因為屬性 'quaxxor' 從來沒有被新增 + obj.sparky = 'arf'; // 丟出 TypeError +} + +fail(); + +// 嘗試透過 Object.defineProperty 來改變屬性的值會丟出 TypeError +Object.defineProperty(obj, 'ohai', { value: 17 }); +Object.defineProperty(obj, 'foo', { value: 'eit' }); + +// 一樣不可能改變物件的原型,都會丟出 TypeError +Object.setPrototypeOf(obj, { x: 20 }) +obj.__proto__ = { x: 20 } +</pre> + +<h3 id="凍結陣列">凍結陣列</h3> + +<pre>let a = [0]; +Object.freeze(a); // 現在這個陣列不能被改動 + +a[0]=1; // 沈默地失敗 +a.push(2); // 沈默地失敗 + +// 在嚴格模式底下會丟出 TypeError +function fail() { + "use strict" + a[0] = 1; + a.push(2); +} + +fail();</pre> + +<p>被凍結的物件是<em>不可變 (Immutable) </em>的。然而,它並不等於常數<em> (constant)</em>。以下的範例顯示一個被凍結的物件並不是常數 (凍結的動作是「淺」的 - 如果資料屬性也是物件, 不會遞迴地做凍結的動作)。</p> + +<pre class="brush: js">obj1 = { + internal: {} +}; + +Object.freeze(obj1); +obj1.internal.a = 'aValue'; + +obj1.internal.a // 'aValue'</pre> + +<p class="brush: js">如果要成為一個常數物件,整個物件參考圖 (包含直接指向或間接指向其他物件) 必須都只能指向被凍結的不可變物件。一個物件被稱作不可變是因為它的整個物件狀態 (值或是指向其他物件的參考) 是固定的。注意,string, number 和 boolean 這些原始型別的值是永遠不變的,Function 和 Array 都屬於物件的一種。</p> + +<p class="brush: js">要讓一個物件變成常數物件,就必須遞迴地凍結每個是物件型別的屬性 (稱作深凍結)。只有當你知道物件的參考圖不存在任何<em><a href="https://en.wikipedia.org/wiki/Cycle_(graph_theory)">循環</a> </em>的時候才能使用以上遞迴的方式來凍結物件,不然就可能會造成無窮迴圈。一個改善以下範例中 deepFreeze() 來解決無窮迴圈問題的方法是 - 創建一個接受一個路徑參數 (像是陣列) 的內部用函數,用來避免無窮遞迴地呼叫 deepFreeze() - 當發現欲凍結的物件已經出現在之前凍結的物件行列中就不繼續遞迴下去。需要注意的是你可能會不小心凍結一個不應該被凍結的物件,像是 [window]。</p> + +<pre class="brush: js">// 用這個函數來進行對物件的深凍結 +function deepFreeze(obj) { + + // 取得物件的所有屬性名稱 + var propNames = Object.getOwnPropertyNames(obj); + + // 在凍結物件本身之前先凍結物件的所有物件屬性 + propNames.forEach(function(name) { + var prop = obj[name]; + + // 凍結 prop 如果它是一個物件 + if (typeof prop == 'object' && prop !== null) + deepFreeze(prop); + }); + + // 凍結本身 (no-op 如果已經被凍結了) + return Object.freeze(obj); +} + +obj2 = { + internal: {} +}; + +deepFreeze(obj2); +obj2.internal.a = 'anotherValue'; +obj2.internal.a; // undefined</pre> + +<h2 id="備註">備註</h2> + +<p>在 ES5 中,如果傳入此方法的參數不是一個物件 (原始型別),{{jsxref("TypeError")}} 就會被丟出。而在 ES2015,一個非物件型態的參數會被當成是一個已經被凍結的物件,所以會被直接回傳?不會造成錯誤。</p> + +<pre class="brush: js">> Object.freeze(1) +TypeError: 1 is not an object // ES5 code + +> Object.freeze(1) +1 // ES2015 code +</pre> + +<h3 id="與_Object.seal()_的差別">與 <code>Object.seal()</code> 的差別</h3> + +<p>被 <code>Object.seal()</code> 密封的物件還是可以改變它原有屬性的值。而被 <code>Object.freeze()</code> 凍結的物件則無法改變它原有屬性的值因為他們是不可變的。</p> + +<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.9', 'Object.freeze')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>第一版。實作於 JavaScript 1.8.5.</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-object.freeze', 'Object.freeze')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object.freeze', 'Object.freeze')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Object.freeze")}}</p> +</div> + +<h2 id="參閱">參閱</h2> + +<ul> + <li>{{jsxref("Object.isFrozen()")}}</li> + <li>{{jsxref("Object.preventExtensions()")}}</li> + <li>{{jsxref("Object.isExtensible()")}}</li> + <li>{{jsxref("Object.seal()")}}</li> + <li>{{jsxref("Object.isSealed()")}}</li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/getprototypeof/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/getprototypeof/index.html new file mode 100644 index 0000000000..ff4e4d480f --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/getprototypeof/index.html @@ -0,0 +1,128 @@ +--- +title: Object.getPrototypeOf() +slug: Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf +tags: + - JavaScript + - Method + - Object +translation_of: Web/JavaScript/Reference/Global_Objects/Object/getPrototypeOf +--- +<div>{{JSRef}}</div> + +<p><code><strong>Object.getPrototypeOf()</strong></code> 回傳指定物件的原型,換句話說,就是取得該物件的 <code>[[Prototype]]</code> 屬性的值).</p> + +<h2 id="表達式">表達式</h2> + +<pre class="syntaxbox"><code>Object.getPrototypeOf(<var>obj</var>)</code></pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>obj</code></dt> + <dd>欲取得原型的物件。</dd> +</dl> + +<h2 id="範例">範例</h2> + +<pre class="brush: js">var proto = {}; +var obj = Object.create(proto); +Object.getPrototypeOf(obj) === proto; // true +</pre> + +<h2 id="備註">備註</h2> + +<p>如果 <code>obj</code> 參數在 ES5 並不是物件時會拋出 {{jsxref("TypeError")}} 例外,同樣狀況在 ES6 時該參數將會被強制轉換成 {{jsxref("Object")}}。</p> + +<pre class="brush: js">Object.getPrototypeOf("foo"); +// TypeError: "foo" is not an object (ES5 code) +Object.getPrototypeOf("foo"); +// String.prototype (ES6 code) +</pre> + +<h2 id="規範">規範</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>{{SpecName('ES5.1', '#sec-15.2.3.2', 'Object.getPrototypeOf')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition.</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-object.getprototypeof', 'Object.getProtoypeOf')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatChrome("5")}}</td> + <td>{{CompatGeckoDesktop("1.9.1")}}</td> + <td>{{CompatIE("9")}}</td> + <td>{{CompatOpera("12.10")}}</td> + <td>{{CompatSafari("5")}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="Opera_註">Opera 註</h2> + +<p>雖然舊版的 Opera 並不支援 <code>Object.getPrototypeOf()</code>,但是 Opera 從 Opera 10.50 支援非標準的 {{jsxref("Object.proto", "__proto__")}} 屬性。</p> + +<h2 id="參見">參見</h2> + +<ul> + <li>{{jsxref("Object.prototype.isPrototypeOf()")}}</li> + <li>{{jsxref("Object.setPrototypeOf()")}} {{experimental_inline}}</li> + <li>{{jsxref("Object.prototype.__proto__")}}</li> + <li>John Resig 的文章--《 <a class="external" href="http://ejohn.org/blog/objectgetprototypeof/">getPrototypeOf</a> 》</li> + <li>{{jsxref("Reflect.getPrototypeOf()")}}</li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/hasownproperty/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/hasownproperty/index.html new file mode 100644 index 0000000000..1786387141 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/hasownproperty/index.html @@ -0,0 +1,184 @@ +--- +title: Object.prototype.hasOwnProperty() +slug: Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty +tags: + - JavaScript +translation_of: Web/JavaScript/Reference/Global_Objects/Object/hasOwnProperty +--- +<div>{{JSRef}}</div> + +<p><code><strong>hasOwnProperty()</strong></code> 回傳物件是否有該屬性的布林值。</p> + +<h2 id="表達式">表達式</h2> + +<pre class="syntaxbox"><code><var>obj</var>.hasOwnProperty(<var>prop</var>)</code></pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>prop</code></dt> + <dd>屬性名稱。</dd> +</dl> + +<h2 id="說明">說明</h2> + +<p>每個為 {{jsxref("Object")}} 後代的物件都繼承 <code>hasOwnProperty</code> 方法。這個方法可以被使用來決定物件是否擁有特定的直接屬性;跟 {{jsxref("Operators/in", "in")}} 不一樣,這個方法並未檢查物件的原型鏈。</p> + +<h2 id="範例">範例</h2> + +<h3 id="使用_hasOwnProperty_測試屬性是否存在">使用 <code>hasOwnProperty</code> 測試屬性是否存在</h3> + +<p>這個範例顯示 <code>o </code>物件是否擁有名為 <code>prop </code>的屬性:</p> + +<pre class="brush: js">o = new Object(); +o.prop = 'exists'; + +function changeO() { + o.newprop = o.prop; + delete o.prop; +} + +o.hasOwnProperty('prop'); // 回傳 true +changeO(); +o.hasOwnProperty('prop'); // 回傳 false +</pre> + +<h3 id="直接與繼承的屬性">直接與繼承的屬性</h3> + +<p>這個範例區分直接屬性和從原型鍊繼承的屬性:</p> + +<pre class="brush: js">o = new Object(); +o.prop = 'exists'; +o.hasOwnProperty('prop'); // 回傳 true +o.hasOwnProperty('toString'); // 回傳 false +o.hasOwnProperty('hasOwnProperty'); // 回傳 false +</pre> + +<h3 id="遍歷物件的屬性">遍歷物件的屬性</h3> + +<p>這個範例顯示如何不執行繼承的屬性去遍歷物件的屬性。注意 {{jsxref("Statements/for...in", "for...in")}} 已經遍歷了可以被列舉的項目,所以不該基於缺乏不可列舉的屬性(如下)而假設 <code>hasOwnProperty</code> 被嚴格地限制在列舉的項目(如同 {{jsxref("Object.getOwnPropertyNames()")}})。</p> + +<pre class="brush: js">var buz = { + fog: 'stack' +}; + +for (var name in buz) { + if (buz.hasOwnProperty(name)) { + console.log('this is fog (' + name + ') for sure. Value: ' + buz[name]); + } + else { + console.log(name); // toString or something else + } +} +</pre> + +<h3 id="將_hasOwnProperty_作為屬性"><code>將 hasOwnProperty</code> 作為屬性</h3> + +<p>JavaScript 並未保護 <code>hasOwnProperty</code>;因此,如果一個物件擁有一樣的屬性名稱,為了獲得正確的結果需要使用 <em>external</em> <code>hasOwnProperty</code>:</p> + +<pre class="brush: js">var foo = { + hasOwnProperty: function() { + return false; + }, + bar: 'Here be dragons' +}; + +foo.hasOwnProperty('bar'); // 總是回傳 false + +// 使用其他物件的 hasOwnProperty 和 call it with 'this' set to foo +({}).hasOwnProperty.call(foo, 'bar'); // true + +// 從物件的原型使用 hasOwnProperty 也是可行的 +Object.prototype.hasOwnProperty.call(foo, 'bar'); // true +</pre> + +<p>註:在最後一個例子中並未創建任何新的物件。</p> + +<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('ES3')}}</td> + <td>{{Spec2('ES3')}}</td> + <td>Initial definition. Implemented in JavaScript 1.5.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.2.4.5', 'Object.prototype.hasOwnProperty')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-object.prototype.hasownproperty', 'Object.prototype.hasOwnProperty')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/en-US/docs/Enumerability_and_ownership_of_properties">Enumerability and ownership of properties</a></li> + <li>{{jsxref("Object.getOwnPropertyNames()")}}</li> + <li>{{jsxref("Statements/for...in", "for...in")}}</li> + <li>{{jsxref("Operators/in", "in")}}</li> + <li><a href="/en-US/docs/Web/JavaScript/Guide/Inheritance_Revisited">JavaScript Guide: Inheritance revisited</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/index.html new file mode 100644 index 0000000000..3885c44a15 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/index.html @@ -0,0 +1,222 @@ +--- +title: Object +slug: Web/JavaScript/Reference/Global_Objects/Object +tags: + - Constructor + - JavaScript + - NeedsTranslation + - Object + - TopicStub +translation_of: Web/JavaScript/Reference/Global_Objects/Object +--- +<div>{{JSRef}}</div> + +<p><code><strong>Object</strong></code> 建構式可用於建立物件包裝(object wrapper)。</p> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox notranslate">// Object initialiser or literal +{ [ <var>nameValuePair1</var>[, <var>nameValuePair2</var>[, ...<var>nameValuePairN</var>] ] ] } + +// Called as a constructor +new Object([<var>value</var>])</pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>nameValuePair1, nameValuePair2, ... nameValuePair<em>N</em></code></dt> + <dd>Pairs of names (strings) and values (any value) where the name is separated from the value by a colon.</dd> + <dt><code>value</code></dt> + <dd>任意值。</dd> +</dl> + +<h2 id="描述">描述</h2> + +<p>The <code>Object</code> constructor creates an object wrapper for the given value. If the value is {{jsxref("null")}} or {{jsxref("undefined")}}, it will create and return an empty object, otherwise, it will return an object of a Type that corresponds to the given value. If the value is an object already, it will return the value.</p> + +<p>When called in a non-constructor context, <code>Object</code> behaves identically to <code>new Object()</code>.</p> + +<p>也可以參考 <a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/Object_initializer">object initializer / literal syntax</a>.</p> + +<h2 id="Object_建構式屬性"><code>Object</code> 建構式屬性</h2> + +<dl> + <dt><code>Object.length</code></dt> + <dd>Has a value of 1.</dd> + <dt>{{jsxref("Object.prototype")}}</dt> + <dd>Allows the addition of properties to all objects of type Object.</dd> +</dl> + +<h2 id="Object_建構式方法"><code>Object</code> 建構式方法</h2> + +<dl> + <dt>{{jsxref("Object.assign()")}}</dt> + <dd>Creates a new object by copying the values of all enumerable own properties from one or more source objects to a target object.</dd> + <dt>{{jsxref("Object.create()")}}</dt> + <dd>Creates a new object with the specified prototype object and properties.</dd> + <dt>{{jsxref("Object.defineProperty()")}}</dt> + <dd>Adds the named property described by a given descriptor to an object.</dd> + <dt>{{jsxref("Object.defineProperties()")}}</dt> + <dd>Adds the named properties described by the given descriptors to an object.</dd> + <dt>{{jsxref("Object.entries()")}} {{experimental_inline}}</dt> + <dd>Returns an array of a given object's own enumerable property <code>[key, value]</code> pairs.</dd> + <dt>{{jsxref("Object.freeze()")}}</dt> + <dd>Freezes an object: other code can't delete or change any properties.</dd> + <dt>{{jsxref("Object.getOwnPropertyDescriptor()")}}</dt> + <dd>Returns a property descriptor for a named property on an object.</dd> + <dt>{{jsxref("Object.getOwnPropertyDescriptors()")}}</dt> + <dd>Returns an object containing all own property descriptors for an object.</dd> + <dt>{{jsxref("Object.getOwnPropertyNames()")}}</dt> + <dd>Returns an array containing the names of all of the given object's <strong>own</strong> enumerable and non-enumerable properties.</dd> + <dt>{{jsxref("Object.getOwnPropertySymbols()")}}</dt> + <dd>Returns an array of all symbol properties found directly upon a given object.</dd> + <dt>{{jsxref("Object.getPrototypeOf()")}}</dt> + <dd>Returns the prototype of the specified object.</dd> + <dt>{{jsxref("Object.is()")}}</dt> + <dd>Compares if two values are distinguishable (ie. the same)</dd> + <dt>{{jsxref("Object.isExtensible()")}}</dt> + <dd>Determines if extending of an object is allowed.</dd> + <dt>{{jsxref("Object.isFrozen()")}}</dt> + <dd>Determines if an object was frozen.</dd> + <dt>{{jsxref("Object.isSealed()")}}</dt> + <dd>Determines if an object is sealed.</dd> + <dt>{{jsxref("Object.keys()")}}</dt> + <dd>Returns an array containing the names of all of the given object's <strong>own</strong> enumerable properties.</dd> + <dt>{{jsxref("Object.preventExtensions()")}}</dt> + <dd>Prevents any extensions of an object.</dd> + <dt>{{jsxref("Object.seal()")}}</dt> + <dd>Prevents other code from deleting properties of an object.</dd> + <dt>{{jsxref("Object.setPrototypeOf()")}}</dt> + <dd>Sets the prototype (i.e., the internal <code>[[Prototype]]</code> property)</dd> + <dt>{{jsxref("Object.values()")}} {{experimental_inline}}</dt> + <dd>Returns an array of a given object's own enumerable values.</dd> +</dl> + +<h2 id="Object_物件實體與_Object_原型物件"><code>Object</code> 物件實體與 <code>Object</code> 原型物件</h2> + +<p>All objects in JavaScript are descended from <code>Object</code>; all objects inherit methods and properties from {{jsxref("Object.prototype")}}, although they may be overridden. For example, other constructors' prototypes override the <code>constructor</code> property and provide their own <code>toString()</code> methods. Changes to the <code>Object</code> prototype object are propagated to all objects unless the properties and methods subject to those changes are overridden further along the prototype chain.</p> + +<h3 id="屬性">屬性</h3> + +<div>{{page('/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype', '屬性') }}</div> + +<h3 id="方法">方法</h3> + +<div>{{page('/zh-TW/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype', '方法') }}</div> + +<h2 id="範例">範例</h2> + +<h3 id="Using_Object_given_undefined_and_null_types">Using <code>Object</code> given <code>undefined</code> and <code>null</code> types</h3> + +<p>下面例子儲存一個空物件至變數o</p> + +<pre class="brush: js notranslate">var o = new Object(); +</pre> + +<pre class="brush: js notranslate">var o = new Object(undefined); +</pre> + +<pre class="brush: js notranslate">var o = new Object(null); +</pre> + +<h3 id="Using_Object_to_create_Boolean_objects">Using <code>Object</code> to create <code>Boolean</code> objects</h3> + +<p>下面例子儲存 {{jsxref("Boolean")}} 物件在 <code>o</code>:</p> + +<pre class="brush: js notranslate">// equivalent to o = new Boolean(true); +var o = new Object(true); +</pre> + +<pre class="brush: js notranslate">// equivalent to o = new Boolean(false); +var o = new Object(Boolean()); +</pre> + +<h2 id="規範">規範</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>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.0.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.2', 'Object')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td></td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-object-objects', 'Object')}}</td> + <td>{{Spec2('ES6')}}</td> + <td>Added Object.assign, Object.getOwnPropertySymbols, Object.setPrototypeOf, Object.is</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object-objects', 'Object')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td>Added Object.entries, Object.values and Object.getOwnPropertyDescriptors.</td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/zh-TW/docs/Web/JavaScript/Reference/Operators/Object_initializer">Object initializer</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/keys/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/keys/index.html new file mode 100644 index 0000000000..958b9a3a47 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/keys/index.html @@ -0,0 +1,208 @@ +--- +title: Object.keys() +slug: Web/JavaScript/Reference/Global_Objects/Object/keys +tags: + - ECMAScript 5 + - JavaScript +translation_of: Web/JavaScript/Reference/Global_Objects/Object/keys +--- +<div>{{JSRef}}</div> + +<p><code><strong>Object.keys()</strong></code> 方法會回傳一個由指定物件所有可列舉之屬性組成的陣列,該陣列中的的排列順序與使用 {{jsxref("Statements/for...in", "for...in")}} 進行迭代的順序相同(兩者的差異在於 <code>for-in</code> 迴圈還會迭代出物件自其原型鏈所繼承來的可列舉屬性)。</p> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox"><code>Object.keys(<var>obj</var>)</code></pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>obj</code></dt> + <dd>物件,用以回傳其可列舉屬性。</dd> +</dl> + +<h3 id="回傳值">回傳值</h3> + +<p>回傳一個包含給定物件內所有可列舉屬性的字串陣列。</p> + +<h2 id="描述">描述</h2> + +<p><code>Object.keys()</code> 回傳一個陣列,陣列中的各元素為直屬於 <code>obj</code> ,對應可列舉屬性名的字串。回傳結果的排序,與手動對物件屬性作迴圈迭代的結果排序相同。</p> + +<h2 id="範例">範例</h2> + +<pre class="brush: js">var arr = ['a', 'b', 'c']; +console.log(Object.keys(arr)); // console: ['0', '1', '2'] + +// 類似陣列的物件 +var obj = { 0: 'a', 1: 'b', 2: 'c' }; +console.log(Object.keys(obj)); // console: ['0', '1', '2'] + +// 擁有隨機 key 排序,類似陣列的物件 +var an_obj = { 100: 'a', 2: 'b', 7: 'c' }; +console.log(Object.keys(an_obj)); // console: ['2', '7', '100'] + +// getFoo 不是可列舉的屬性 +var my_obj = Object.create({}, { + getFoo: { + value: function() { return this.foo; } + } +}); +my_obj.foo = 1; + +console.log(Object.keys(my_obj)); // console: ['foo'] +</pre> + +<p>如果想取得物件的所有屬性,包括非可列舉的屬性,請參閱 {{jsxref("Object.getOwnPropertyNames()")}}.</p> + +<h2 id="備註">備註</h2> + +<p>在 ES5 中,如果這個方法的參數不是一個標準物件(例如原始型別),將會產生 {{jsxref("TypeError")}}錯誤。而在 ES2015,非物件的參數將會強制轉換成物件。</p> + +<pre class="brush: js">Object.keys("foo"); +// TypeError: "foo" is not an object (ES5 code) + +Object.keys("foo"); +// ["0", "1", "2"] (ES2015 code) +</pre> + +<h2 id="Polyfill">Polyfill</h2> + +<p>如需在原生不支援、較舊的環境中增加 <code>Object.keys</code> 的相容性,請複製以下片段:</p> + +<pre class="brush: js">// From https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/keys +if (!Object.keys) { + Object.keys = (function() { + 'use strict'; + var hasOwnProperty = Object.prototype.hasOwnProperty, + hasDontEnumBug = !({ toString: null }).propertyIsEnumerable('toString'), + dontEnums = [ + 'toString', + 'toLocaleString', + 'valueOf', + 'hasOwnProperty', + 'isPrototypeOf', + 'propertyIsEnumerable', + 'constructor' + ], + dontEnumsLength = dontEnums.length; + + return function(obj) { + if (typeof obj !== 'object' && (typeof obj !== 'function' || obj === null)) { + throw new TypeError('Object.keys called on non-object'); + } + + var result = [], prop, i; + + for (prop in obj) { + if (hasOwnProperty.call(obj, prop)) { + result.push(prop); + } + } + + if (hasDontEnumBug) { + for (i = 0; i < dontEnumsLength; i++) { + if (hasOwnProperty.call(obj, dontEnums[i])) { + result.push(dontEnums[i]); + } + } + } + return result; + }; + }()); +} +</pre> + +<p>請注意以上的代碼片段在 IE7 中( IE8 也有可能 ),從不同的 window 傳入物件將包含非可列舉的 key 。</p> + +<p>較精簡的瀏覽器 Polyfill,請參閱 <a href="http://tokenposts.blogspot.com.au/2012/04/javascript-objectkeys-browser.html">Javascript - Object.keys Browser Compatibility</a>.</p> + +<h2 id="規範">規範</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>{{SpecName('ES5.1', '#sec-15.2.3.14', 'Object.keys')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.8.5.</td> + </tr> + <tr> + <td>{{SpecName('ES2015', '#sec-object.keys', 'Object.keys')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object.keys', 'Object.keys')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatChrome("5")}}</td> + <td>{{CompatGeckoDesktop("2.0")}}</td> + <td>{{CompatIE("9")}}</td> + <td>{{CompatOpera("12")}}</td> + <td>{{CompatSafari("5")}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/en-US/docs/Enumerability_and_ownership_of_properties">Enumerability and ownership of properties</a></li> + <li>{{jsxref("Object.prototype.propertyIsEnumerable()")}}</li> + <li>{{jsxref("Object.create()")}}</li> + <li>{{jsxref("Object.getOwnPropertyNames()")}}</li> + <li>{{jsxref("Object.values()")}} {{experimental_inline}}</li> + <li>{{jsxref("Object.entries()")}} {{experimental_inline}}</li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/preventextensions/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/preventextensions/index.html new file mode 100644 index 0000000000..bc046cf87b --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/preventextensions/index.html @@ -0,0 +1,179 @@ +--- +title: Object.preventExtensions() +slug: Web/JavaScript/Reference/Global_Objects/Object/preventExtensions +translation_of: Web/JavaScript/Reference/Global_Objects/Object/preventExtensions +--- +<div>{{JSRef}}</div> + +<p><code><strong>Object.preventExtensions()</strong></code> 用來避免物件被新增新的屬性。</p> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox"><code>Object.preventExtensions(<var>obj</var>)</code></pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>obj</code></dt> + <dd>要被用作無法擴充的物件。</dd> +</dl> + +<h2 id="描述">描述</h2> + +<p>物件如果可以被增加新的屬性,我們稱它可以被擴充(extensible)。<code>Object.preventExtensions()</code> 標註物件使它無法被擴充,所以在它被標註為無法擴充當下,它將無法再增加新的屬性。不過注意一點,在一般狀況下,被標註為無法擴充的物件,其屬性仍可被刪除(<em>deleted</em>)。嘗試去增加屬性將會導致失敗,可能會沒有結果產生,或是傳回一個 {{jsxref("TypeError")}} (最常見,但並不是一定,當在{{jsxref("Functions_and_function_scope/Strict_mode", "strict mode", "", 1)}})。</p> + +<p><code>Object.preventExtensions() 只有避免物件被增加屬性,屬性仍可以被增加至 </code>object prototype 。不過,呼叫 <code>Object.preventExtensions() 使用在物件上,就可以使其 </code>{{jsxref("Object.proto", "__proto__")}} {{deprecated_inline}} 屬性無法被擴充。</p> + +<p>如果能把可擴充物件,轉成無法擴充物件,在 ECMAScript 5 規範中,它並沒有任何方法轉回來。</p> + +<h2 id="範例">範例</h2> + +<pre class="brush: js">// Object.preventExtensions 傳回一個被無法擴充的物件 +var obj = {}; +var obj2 = Object.preventExtensions(obj); +obj === obj2; // true + +// 預設下,物件可以被擴充 +var empty = {}; +Object.isExtensible(empty); // === true + +// ...但是以下情況之後,無法再被變更。 +Object.preventExtensions(empty); +Object.isExtensible(empty); // === false + +// Object.defineProperty throws 當為無法擴充的物件增加屬性 +var nonExtensible = { removable: true }; +Object.preventExtensions(nonExtensible); +Object.defineProperty(nonExtensible, 'new', { value: 8675309 }); // throws a TypeError + +// 在 strict mode 中,嘗試去新增屬性給無法擴充物件,將 throws 出一個 TypeError。 +function fail() { + 'use strict'; + nonExtensible.newProperty = 'FAIL'; // throws a TypeError +} +fail(); + +// EXTENSION (only works in engines supporting __proto__ +// (which is deprecated. Use Object.getPrototypeOf instead)): +// A non-extensible object's prototype is immutable. +var fixed = Object.preventExtensions({}); +fixed.__proto__ = { oh: 'hai' }; // throws a TypeError +</pre> + +<h2 id="筆記">筆記</h2> + +<p>在ES5中,如果給祝個方法的參數為非物件,它將造成一個 {{jsxref("TypeError")}} 。不過在 ES6 中,非物件參數會被正常處理。另外,如果它原本就是個無法擴充物件,就只是回傳本身。</p> + +<pre class="brush: js">Object.preventExtensions(1); +// TypeError: 1 is not an object (ES5 code) + +Object.preventExtensions(1); +// 1 (ES6 code) +</pre> + +<h2 id="規範">規範</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>{{SpecName('ES5.1', '#sec-15.2.3.10', 'Object.preventExtensions')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.8.5.</td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-object.preventextensions', 'Object.preventExtensions')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-object.preventextensions', 'Object.preventExtensions')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容度">瀏覽器相容度</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatChrome("6")}}</td> + <td>{{CompatGeckoDesktop("2.0")}}</td> + <td>{{CompatIE("9")}}</td> + <td>{{CompatOpera("12")}}</td> + <td>{{CompatSafari("5.1")}}</td> + </tr> + <tr> + <td>ES6 behavior for non-object argument</td> + <td>{{CompatChrome("44")}}</td> + <td>{{CompatGeckoDesktop("35.0")}}</td> + <td>{{CompatIE("11")}}</td> + <td>{{CompatOpera("31")}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + <tr> + <td>ES6 behavior for non-object argument</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatGeckoMobile("35.0")}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + <td>{{CompatUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="閱讀更多">閱讀更多</h2> + +<ul> + <li>{{jsxref("Object.isExtensible()")}}</li> + <li>{{jsxref("Object.seal()")}}</li> + <li>{{jsxref("Object.isSealed()")}}</li> + <li>{{jsxref("Object.freeze()")}}</li> + <li>{{jsxref("Object.isFrozen()")}}</li> + <li>{{jsxref("Reflect.preventExtensions()")}}</li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/proto/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/proto/index.html new file mode 100644 index 0000000000..5ba5c8f615 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/proto/index.html @@ -0,0 +1,137 @@ +--- +title: Object.prototype.__proto__ +slug: Web/JavaScript/Reference/Global_Objects/Object/proto +translation_of: Web/JavaScript/Reference/Global_Objects/Object/proto +--- +<div class="warning"> +<p><strong>Warning:</strong> 基於現代Javascript引擎最佳化物件屬性存取的方法,改變一個物件的 <code>[[Prototype]]</code> 在任何瀏覽器或是Javascript引擎都是非常慢的操作?。改變繼承屬性對效能的影響微妙且深遠,不僅僅只是影響執行 <code>obj.__proto__ = ...</code> 的時間,而是會影響到所有有存取到被改變 <code>[[Prototype]]</code> 的物件的程式碼的執行時間。如果你在乎效能的話就應該避免改變一個物件的 <code>[[Prototype]]</code> 。反之,請用 {{jsxref("Object.create()")}} 來產生一個擁有 <code>[[Prototype]]</code> 的物件。</p> +</div> + +<div class="warning"> +<p><strong>Warning:</strong> 雖然 <code>Object.prototype.__proto__</code> 在今日已經被絕大部分的瀏覽器所支援,其存在與確切的行為只有在 ECMAScript 2015 規範才被標準化成一個歷史功能來確保相容性。為了更好的支援,建議使用{{jsxref("Object.getPrototypeOf()")}}。</p> +</div> + +<div>{{JSRef}}</div> + +<p>The <code>__proto__</code> property of {{jsxref("Object.prototype")}} is an accessor property (a getter function and a setter function) that exposes the internal <code>[[Prototype]]</code> (either an object or {{jsxref("Global_Objects/null", "null")}}) of the object through which it is accessed.</p> + +<p>The use of <code>__proto__</code> is controversial, and has been discouraged. It was never originally included in the EcmaScript language spec, but modern browsers decided to implement it anyway. Only recently, the <code>__proto__</code> property has been standardized in the ECMAScript 2015 language specification for web browsers to ensure compatibility, so will be supported into the future. It is deprecated in favor of {{jsxref("Object.getPrototypeOf")}}/{{jsxref("Reflect.getPrototypeOf")}} and {{jsxref("Object.setPrototypeOf")}}/{{jsxref("Reflect.setPrototypeOf")}} (though still, setting the <code>[[Prototype]]</code> of an object is a slow operation that should be avoided if performance is a concern).</p> + +<p>The <code>__proto__</code> property can also be used in an object literal definition to set the object <code>[[Prototype]]</code> on creation, as an alternative to {{jsxref("Object.create()")}}. See: <a href="/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer">object initializer / literal syntax</a>.</p> + +<h2 id="Syntax">Syntax</h2> + +<pre class="brush: js">var Circle = function () {}; +var shape = {}; +var circle = new Circle(); + +// Set the object prototype. +// DEPRECATED. This is for example purposes only. DO NOT DO THIS in real code. +shape.__proto__ = circle; + +// Get the object prototype +console.log(shape.__proto__ === circle); // true +</pre> + +<pre class="brush: js">var shape = function () {}; +var p = { + a: function () { + console.log('aaa'); + } +}; +shape.prototype.__proto__ = p; + +var circle = new shape(); +circle.a(); // aaa +console.log(shape.prototype === circle.__proto__); // true + +// or +var shape = function () {}; +var p = { + a: function () { + console.log('a'); + } +}; + +var circle = new shape(); +circle.__proto__ = p; +circle.a(); // a +console.log(shape.prototype === circle.__proto__); // false + +// or +function test() {}; +test.prototype.myname = function () { + console.log('myname'); +}; + +var a = new test(); +console.log(a.__proto__ === test.prototype); // true +a.myname(); // myname + + +// or +var fn = function () {}; +fn.prototype.myname = function () { + console.log('myname'); +}; + +var obj = { + __proto__: fn.prototype +}; + +obj.myname(); // myname +</pre> + +<p>Note: that is two underscores, followed by the five characters "proto", followed by two more underscores.</p> + +<h2 id="Description">Description</h2> + +<p>The <code>__proto__</code> getter function exposes the value of the internal <code>[[Prototype]]</code> of an object. For objects created using an object literal, this value is {{jsxref("Object.prototype")}}. For objects created using array literals, this value is {{jsxref("Array.prototype")}}. For functions, this value is {{jsxref("Function.prototype")}}. For objects created using <code>new fun</code>, where <code>fun</code> is one of the built-in constructor functions provided by JavaScript ({{jsxref("Array")}}, {{jsxref("Boolean")}}, {{jsxref("Date")}}, {{jsxref("Number")}}, {{jsxref("Object")}}, {{jsxref("String")}}, and so on — including new constructors added as JavaScript evolves), this value is always <code>fun.prototype</code>. For objects created using <code>new fun</code>, where <code>fun</code> is a function defined in a script, this value is the value of <code>fun.prototype</code>. (That is, if the constructor didn't return an other object explicitly, or the <code>fun.prototype</code> has been reassigned since the instance was created).</p> + +<p>The <code>__proto__</code> setter allows the <code>[[Prototype]]</code> of an object to be mutated. The object must be extensible according to {{jsxref("Object.isExtensible()")}}: if it is not, a {{jsxref("Global_Objects/TypeError", "TypeError")}} is thrown. The value provided must be an object or {{jsxref("Global_Objects/null", "null")}}. Providing any other value will do nothing.</p> + +<p>To understand how prototypes are used for inheritance, see guide article <a href="/en-US/docs/Web/JavaScript/Guide/Inheritance_and_the_prototype_chain">Inheritance and the prototype chain</a>.</p> + +<p>The <code>__proto__</code> property is a simple accessor property on {{jsxref("Object.prototype")}} consisting of a getter and setter function. A property access for <code>__proto__</code> that eventually consults {{jsxref("Object.prototype")}} will find this property, but an access that does not consult {{jsxref("Object.prototype")}} will not find it. If some other <code>__proto__</code> property is found before {{jsxref("Object.prototype")}} is consulted, that property will hide the one found on {{jsxref("Object.prototype")}}.</p> + +<h2 id="Specifications">Specifications</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>{{SpecName('ES2015', '#sec-additional-properties-of-the-object.prototype-object', 'Object.prototype.__proto__')}}</td> + <td>{{Spec2('ES2015')}}</td> + <td>Included in the (normative) annex for additional ECMAScript legacy features for Web browsers (note that the specification codifies what is already in implementations).</td> + </tr> + <tr> + <td>{{SpecName('ESDraft', '#sec-additional-properties-of-the-object.prototype-object', 'Object.prototype.__proto__')}}</td> + <td>{{Spec2('ESDraft')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility">Browser compatibility</h2> + +<div> + + +<p>{{Compat("javascript.builtins.Object.proto")}}</p> +</div> + +<h2 id="Compatibility_notes">Compatibility notes</h2> + +<p>While the ECMAScript 2015 specification dictates that support for <code>__proto__</code> is required <em>only</em> for web browsers (although being normative), other environments may support it as well for legacy usage.</p> + +<h2 id="See_also">See also</h2> + +<ul> + <li>{{jsxref("Object.prototype.isPrototypeOf()")}}</li> + <li>{{jsxref("Object.getPrototypeOf()")}}</li> + <li>{{jsxref("Object.setPrototypeOf()")}}</li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/prototype/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/prototype/index.html new file mode 100644 index 0000000000..21c2a53985 --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/prototype/index.html @@ -0,0 +1,218 @@ +--- +title: Object.prototype +slug: Web/JavaScript/Reference/Global_Objects/Object/prototype +tags: + - JavaScript + - Object + - 待翻譯 +translation_of: Web/JavaScript/Reference/Global_Objects/Object +--- +<div>{{JSRef}}</div> + +<p><code><strong>Object.prototype</strong></code> 代表 {{jsxref("Object")}} 的原型物件。</p> + +<div>{{js_property_attributes(0, 0, 0)}}</div> + +<h2 id="描述">描述</h2> + +<p>All objects in JavaScript are descended from {{jsxref("Object")}}; all objects inherit methods and properties from <code>Object.prototype</code>, although they may be overridden (except an <code>Object</code> with a <code>null</code> prototype, i.e. <code>Object.create(null)</code>). For example, other constructors' prototypes override the <code>constructor</code> property and provide their own {{jsxref("Object.prototype.toString()", "toString()")}} methods. Changes to the <code>Object</code> prototype object are propagated to all objects unless the properties and methods subject to those changes are overridden further along the prototype chain.</p> + +<h2 id="屬性">屬性</h2> + +<dl> + <dt>{{jsxref("Object.prototype.constructor")}}</dt> + <dd>Specifies the function that creates an object's prototype.</dd> + <dt>{{jsxref("Object.prototype.__proto__")}} {{non-standard_inline}}</dt> + <dd>Points to the object which was used as prototype when the object was instantiated.</dd> + <dt>{{jsxref("Object.prototype.__noSuchMethod__")}} {{non-standard_inline}}</dt> + <dd>Allows a function to be defined that will be executed when an undefined object member is called as a method.</dd> + <dt><s class="obsoleteElement">{{jsxref("Object.prototype.__count__")}} {{obsolete_inline}}</s></dt> + <dd><s class="obsoleteElement">Used to return the number of enumerable properties directly on a user-defined object, but has been removed.</s></dd> + <dt><s class="obsoleteElement">{{jsxref("Object.prototype.__parent__")}} {{obsolete_inline}}</s></dt> + <dd><s class="obsoleteElement">Used to point to an object's context, but has been removed.</s></dd> +</dl> + +<h2 id="方法">方法</h2> + +<dl> + <dt>{{jsxref("Object.prototype.__defineGetter__()")}} {{non-standard_inline}} {{deprecated_inline}}</dt> + <dd>Associates a function with a property that, when accessed, executes that function and returns its return value.</dd> + <dt>{{jsxref("Object.prototype.__defineSetter__()")}} {{non-standard_inline}} {{deprecated_inline}}</dt> + <dd>Associates a function with a property that, when set, executes that function which modifies the property.</dd> + <dt>{{jsxref("Object.prototype.__lookupGetter__()")}} {{non-standard_inline}} {{deprecated_inline}}</dt> + <dd>Returns the function associated with the specified property by the {{jsxref("Object.defineGetter", "__defineGetter__")}} method.</dd> + <dt>{{jsxref("Object.prototype.__lookupSetter__()")}} {{non-standard_inline}} {{deprecated_inline}}</dt> + <dd>Returns the function associated with the specified property by the {{jsxref("Object.defineSetter", "__defineSetter__")}} method.</dd> + <dt>{{jsxref("Object.prototype.hasOwnProperty()")}}</dt> + <dd>Returns a boolean indicating whether an object contains the specified property as a direct property of that object and not inherited through the prototype chain.</dd> + <dt>{{jsxref("Object.prototype.isPrototypeOf()")}}</dt> + <dd>Returns a boolean indication whether the specified object is in the prototype chain of the object this method is called upon.</dd> + <dt>{{jsxref("Object.prototype.propertyIsEnumerable()")}}</dt> + <dd>Returns a boolean indicating if the internal <a href="/en-US/docs/ECMAScript_DontEnum_attribute" title="ECMAScript_DontEnum_attribute">ECMAScript DontEnum attribute</a> is set.</dd> + <dt>{{jsxref("Object.prototype.toSource()")}} {{non-standard_inline}}</dt> + <dd>Returns string containing the source of an object literal representing the object that this method is called upon; you can use this value to create a new object.</dd> + <dt>{{jsxref("Object.prototype.toLocaleString()")}}</dt> + <dd>Calls {{jsxref("Object.toString", "toString()")}}.</dd> + <dt>{{jsxref("Object.prototype.toString()")}}</dt> + <dd>Returns a string representation of the object.</dd> + <dt>{{jsxref("Object.prototype.unwatch()")}} {{non-standard_inline}}</dt> + <dd>Removes a watchpoint from a property of the object.</dd> + <dt>{{jsxref("Object.prototype.valueOf()")}}</dt> + <dd>Returns the primitive value of the specified object.</dd> + <dt>{{jsxref("Object.prototype.watch()")}} {{non-standard_inline}}</dt> + <dd>Adds a watchpoint to a property of the object.</dd> + <dt><s class="obsoleteElement">{{jsxref("Object.prototype.eval()")}} {{obsolete_inline}}</s></dt> + <dd><s class="obsoleteElement">Used to evaluate a string of JavaScript code in the context of the specified object, but has been removed.</s></dd> +</dl> + +<h2 id="範例">範例</h2> + +<p>因為 JavaScript 並沒有子類別的物件,所以原型是個很有用的解決辦法, 使某些函數作為物件的基本類別物件。例如:</p> + +<pre class="brush: js">var Person = function() { + this.canTalk = true; +}; + +Person.prototype.greet = function() { + if (this.canTalk) { + console.log('Hi, I am ' + this.name); + } +}; + +var Employee = function(name, title) { + Person.call(this); + this.name = name; + this.title = title; +}; + +Employee.prototype = Object.create(Person.prototype); +Employee.prototype.constructor = Employee; + +Employee.prototype.greet = function() { + if (this.canTalk) { + console.log('Hi, I am ' + this.name + ', the ' + this.title); + } +}; + +var Customer = function(name) { + Person.call(this); + this.name = name; +}; + +Customer.prototype = Object.create(Person.prototype); +Customer.prototype.constructor = Customer; + +var Mime = function(name) { + Person.call(this); + this.name = name; + this.canTalk = false; +}; + +Mime.prototype = Object.create(Person.prototype); +Mime.prototype.constructor = Mime; + +var bob = new Employee('Bob', 'Builder'); +var joe = new Customer('Joe'); +var rg = new Employee('Red Green', 'Handyman'); +var mike = new Customer('Mike'); +var mime = new Mime('Mime'); + +bob.greet(); +// Hi, I am Bob, the Builder + +joe.greet(); +// Hi, I am Joe + +rg.greet(); +// Hi, I am Red Green, the Handyman + +mike.greet(); +// Hi, I am Mike + +mime.greet(); +</pre> + +<h2 id="規範">規範</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>{{SpecName('ES1')}}</td> + <td>{{Spec2('ES1')}}</td> + <td>Initial definition. Implemented in JavaScript 1.0.</td> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.2.3.1', 'Object.prototype')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-object.prototype', 'Object.prototype')}}</td> + <td>{{Spec2('ES6')}}</td> + <td> </td> + </tr> + </tbody> +</table> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatVersionUnknown}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="參見">參見</h2> + +<ul> + <li><a href="/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript">Introduction to Object-Oriented JavaScript</a></li> +</ul> diff --git a/files/zh-tw/web/javascript/reference/global_objects/object/watch/index.html b/files/zh-tw/web/javascript/reference/global_objects/object/watch/index.html new file mode 100644 index 0000000000..9dc8afa27f --- /dev/null +++ b/files/zh-tw/web/javascript/reference/global_objects/object/watch/index.html @@ -0,0 +1,191 @@ +--- +title: Object.prototype.watch() +slug: Web/JavaScript/Reference/Global_Objects/Object/watch +translation_of: Archive/Web/JavaScript/Object.watch +--- +<div>{{JSRef}}</div> + +<div class="warning"> +<p><strong>Warning:</strong> Generally you should avoid using <code>watch()</code> and {{jsxref("Object.prototype.unwatch", "unwatch()")}} when possible. These two methods are implemented only in Gecko, and they're intended primarily for debugging use. In addition, using watchpoints has a serious negative impact on performance, which is especially true when used on global objects, such as <code>window</code>. You can usually use <a href="/en-US/docs/Web/JavaScript/Guide/Working_with_Objects#Defining_getters_and_setters">setters and getters</a> or proxies instead. See {{anch("Browser compatibility")}} for details. Also, do not confuse {{jsxref("Object.prototype.watch", "Object.watch")}} with {{jsxref("Object.prototype.observe", "Object.observe")}}.</p> +</div> + +<p>The <code><strong>watch()</strong></code> method watches for a property to be assigned a value and runs a function when that occurs.</p> + +<h2 id="語法">語法</h2> + +<pre class="syntaxbox"><code><var>obj</var>.watch(<var>prop</var>, <var>handler</var>)</code></pre> + +<h3 id="參數">參數</h3> + +<dl> + <dt><code>prop</code></dt> + <dd>所需要監聽其值是否改變的物件屬性</dd> + <dt><code>handler</code></dt> + <dd>當監聽的變數其數值變換時所執行的function</dd> +</dl> + +<h3 id="回傳值">回傳值</h3> + +<p>{{jsxref("undefined")}}.</p> + +<h2 id="Description">Description</h2> + +<p>Watches for assignment to a property named <code>prop</code> in this object, 呼叫 <code>handler(prop, oldval, newval)</code> whenever <code>prop</code> is set and storing the return value in that property. A watchpoint can filter (or nullify) the value assignment, by returning a modified <code>newval</code> (or by returning <code>oldval</code>).</p> + +<p>當你刪掉所監聽的物件屬性,並不會結束針對該物件屬性的監聽。當你重新產生該屬性時,監聽依舊維持作用。</p> + +<p>要停止該次監聽, 須使用 {{jsxref("Object.unwatch", "unwatch()")}} 函式. By default, the <code>watch</code> method is inherited by every object descended from {{jsxref("Object")}}.</p> + +<p>The JavaScript debugger has functionality similar to that provided by this method, as well as other debugging options. For information on the debugger, see <a href="/en-US/docs/Venkman">Venkman</a>.</p> + +<p>In Firefox, <code>handler</code> is only called from assignments in script, not from native code. For example, <code>window.watch('location', myHandler)</code> will not call <code>myHandler</code> if the user clicks a link to an anchor within the current document. However, <code>window.location += '#myAnchor'</code> will call <code>myHandler</code>.</p> + +<div class="note"> +<p><strong>Note:</strong> Calling <code>watch()</code> on an object for a specific property overrides any previous handler attached for that property.</p> +</div> + +<h2 id="範例">範例</h2> + +<h3 id="使用watch_和_unwatch">使用watch 和 unwatch</h3> + +<pre class="brush: js">var o = { p: 1 }; + +o.watch('p', function (id, oldval, newval) { + console.log('o.' + id + ' changed from ' + oldval + ' to ' + newval); + return newval; +}); + +o.p = 2; +o.p = 3; +delete o.p; +o.p = 4; + +o.unwatch('p'); +o.p = 5; +</pre> + +<p>上述程式執行結果:</p> + +<pre>o.p changed from 1 to 2 +o.p changed from 2 to 3 +o.p changed from undefined to 4 +</pre> + +<h3 id="使用_watch_驗證物件的屬性">使用 <code>watch</code> 驗證物件的屬性</h3> + +<p>You can use <code>watch</code> to test any assignment to an object's properties. This example ensures that every Person always has a valid name and an age between 0 and 200.</p> + +<pre class="brush: js">Person = function(name, age) { + this.watch('age', Person.prototype._isValidAssignment); + this.watch('name', Person.prototype._isValidAssignment); + this.name = name; + this.age = age; +}; + +Person.prototype.toString = function() { + return this.name + ', ' + this.age; +}; + +Person.prototype._isValidAssignment = function(id, oldval, newval) { + if (id === 'name' && (!newval || newval.length > 30)) { + throw new RangeError('invalid name for ' + this); + } + if (id === 'age' && (newval < 0 || newval > 200)) { + throw new RangeError('invalid age for ' + this); + } + return newval; +} + +will = new Person('Will', 29); +console.log(will); // Will, 29 + +try { + will.name = ''; +} catch (e) { + console.log(e); +} + +try { + will.age = -4; +} catch (e) { + console.log(e); +} +</pre> + +<p>上述程式執行結果:</p> + +<pre>Will, 29 +RangeError: invalid name for Will, 29 +RangeError: invalid age for Will, 29 +</pre> + +<h2 id="規格">規格</h2> + +<p>Not part of any specifications. Implemented in JavaScript 1.2.</p> + +<h2 id="瀏覽器相容性">瀏覽器相容性</h2> + +<div>{{CompatibilityTable}}</div> + +<div id="compat-desktop"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Chrome</th> + <th>Firefox (Gecko)</th> + <th>Internet Explorer</th> + <th>Opera</th> + <th>Safari</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatNo}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + </tr> + </tbody> +</table> +</div> + +<div id="compat-mobile"> +<table class="compat-table"> + <tbody> + <tr> + <th>Feature</th> + <th>Android</th> + <th>Chrome for Android</th> + <th>Firefox Mobile (Gecko)</th> + <th>IE Mobile</th> + <th>Opera Mobile</th> + <th>Safari Mobile</th> + </tr> + <tr> + <td>Basic support</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatVersionUnknown}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + <td>{{CompatNo}}</td> + </tr> + </tbody> +</table> +</div> + +<h2 id="Compatibility_notes">Compatibility notes</h2> + +<ul> + <li>This <a class="external link-https" href="https://gist.github.com/384583">Polyfill</a> offers <code>watch</code> to all ES5 compatible browsers.</li> + <li>Using a {{jsxref("Proxy")}} enables you do even deeper changes to how property assignments work.</li> + <li>Calling <code>watch()</code> on the {{domxref("Document")}} object throws a {{jsxref("TypeError")}} since Firefox 23 ({{bug(903332)}}). This regression has been fixed with Firefox 27.</li> +</ul> + +<h2 id="參閱">參閱</h2> + +<ul> + <li>{{jsxref("Object.unwatch()")}}</li> + <li>{{jsxref("Object.observe()")}} {{obsolete_inline}}</li> +</ul> |