輕鬆學習 JavaScript——第 7 部分:物件屬性描述符

2017-12-13    分類:WEB開發、程式設計開發、首頁精華0人評論發表於2017-12-13

本文由碼農網 – 小峰原創翻譯,轉載請看清文末的轉載要求,歡迎參與我們的付費投稿計劃

在JavaScript中,你可以如下所示建立一個物件字面量:

var cat = {
    name: 'foo',
    age: 9
};

乍一看,好像物件cat有字串和數字值這兩個屬性。然而,這不僅僅是JavaScript直譯器。在ES5中,介紹了屬性描述符的概念。在我們繼續討論屬性描述符之前,讓我們試著回答幾個問題:

  • 如何建立只讀屬性?
  • 如何制定不可列舉的屬性?
  • 如何使屬性不可配置?
  • 如何確定一個屬性是否是隻讀的?

如果你理解屬性描述符,那麼你就可以回答所有這些問題。

請看下面的程式碼:

var cat = {
    name: 'foo',
    age: 9
};
var a = Object.getOwnPropertyDescriptor(cat, 'name');
console.log(a);

輸出將如下所示:

正如你在這裡看到的,這個屬性有四個特徵:

value儲存屬性的資料,而writable,enumerable和configurable則描述屬性的其他特徵。接下來我們將對這些特徵一一闡述。

writable

屬性的值是否可以更改是由writable特徵決定的。如果writable設定為false,那麼屬性的值不能更改,JavaScript將忽略屬性值中的任何更改。請看下面的程式碼:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { writable: false });
console.log(cat.name); // foo 
cat.name = "koo"; // JavaScript will ignore it as writable is set to false 
console.log(cat.name); // foo

你可以使用Object.defineProperty更改writable、enumerable和configurable特徵的值。我們稍後會在這篇文章中詳細討論Object.defineProperty,但正如你在上面的程式碼片段中看到的那樣,我們已經將writable屬性設定為false,從而改變了name屬性的值。JavaScript將忽略重新分配,並且name屬性的值將保持為foo。

如果以嚴格模式執行程式碼,那麼為了重新分配writable設定為false的屬性值,JavaScript將丟擲異常。請看下面的程式碼:

'use strict';
var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { writable: false });
console.log(cat.name); // foo 
cat.name = "koo"; // error

在這裡,JavaScript以嚴格模式執行,因此,當你重新分配name屬性的值時,JavaScript將丟擲異常,如下所示:

這裡的錯誤訊息說,你不能賦值到只讀屬性。也就是說,如果屬性的writable特徵設定為false,那麼屬性將充當只讀屬性。

configurable

屬性的其他特徵是否可以配置取決於configurable的值。如果屬性configurable設定為false,則不能更改writable和enumerable的值。請看下面的程式碼:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { configurable: false });
Object.defineProperty(cat, 'name', { enumerable: false });

在這裡,我們將name屬性的configurable設定為false。之後,我們將enumerable設定為false。如前所述,一旦一個屬性的configurable設定為false,那麼你就不能改變另一個特徵。

對於上面的程式碼,JavaScript會丟擲一個TypeError異常,如下圖所示。你會得到無法重新定義屬性名稱的錯誤:

在使用configurable的時候,你需要記住,改變configurable的值只能做一次。如果將屬性的configurable設定為false,那麼你就不能重新分配它;你無法撤消對configurable的更改。請看下面的程式碼:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { configurable: false });
Object.defineProperty(cat, 'name', { configurable: true });

我們在重新分配name屬性的configurable,但是,JavaScript會對上述操作丟擲一個TypeError,如下圖所示。正如你所看到的,一旦configurable被設定為false,就不能撤銷那個更改。

另一個重要的事情是,即使configurable設定為false,writable也可以從true更改為false——但反之則不然。請看下面的程式碼:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { configurable: false });
Object.defineProperty(cat, 'name', { writable: false });
cat.name = 'koo';
console.log(cat.name); // foo

如果不是在嚴格模式下,上面的程式碼不會丟擲任何異常。正如我們前面所討論的,即使configurable為false,writable也可以從true變為false,反之則不然。另一個需要牢記的重要事項是,你無法刪除configurable設定為false的屬性。

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { configurable: false });
delete cat.name; // wont delete as configurable is false 
console.log(cat.name); // foo 
delete (cat.age); // will be deleted
console.log(cat.age); // undefined

在上面的程式碼中,你會發現JavaScript不會刪除name屬性,因為name屬性的configurable設定為false。

enumerable

對於一個屬性,如果你設定了enumerable:false,那麼這個屬性將不會出現在列舉中,因此它不能用在諸如for … in迴圈這樣的語句中。

請看下面的程式碼:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { enumerable: false });
for (let f in cat) {
    console.log(f); // will print only age 
}

在這裡,你只能得到age,因為name的enumerable被設定為了false。這是另一個需要記住的重要事項:通過設定enumerable:false,唯一的屬性將不可用於列舉。我們來看下面的程式碼:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { enumerable: false });
console.log(cat.name); // foo 
console.log('name' in cat); // true

在這裡,name屬性enumerable設定為false,但你可以訪問它。在檢查name是否屬於cat的屬性時,你也會發現是true。

有時,你可能需要檢查某個特定屬性enumerable是否設定為false或true。你可以通過使用propertyIsEnumerable方法來做到這一點:

var cat = {
    name: 'foo',
    age: 9
};
Object.defineProperty(cat, 'name', { enumerable: false });
console.log(cat.propertyIsEnumerable("name")); // false

結論

作為一名專業的JavaScript開發人員,你必須對JavaScript物件屬性描述符有一個很好的理解,我希望你能從這篇文章中學到一些知識!請繼續關注我們的下一篇文章,繼續學習JavaScript中更重要的概念。

系列目錄

輕鬆學習 JavaScript——第 1 部分:瞭解 let 語句

輕鬆學習 JavaScript——第 2 部分:函式中的 Rest 引數

輕鬆學習 JavaScript——第 3 部分:函式中的預設引數

輕鬆學習 JavaScript——第 4 部分:函式中的 arguments 物件

輕鬆學習 JavaScript——第 5 部分:簡化函式提升

輕鬆學習 JavaScript——第 6 部分:JavaScript 箭頭函式

輕鬆學習 JavaScript——第 7 部分:物件屬性描述符

輕鬆學習 JavaScript——第 8 部分:JavaScript 中的類

譯文連結:http://www.codeceo.com/article/easy-javascript-07-object-property-descriptors.html
英文原文:Easy JavaScript Part 7 : Object Property Descriptors
翻譯作者:碼農網 – 小峰
轉載必須在正文中標註並保留原文連結、譯文連結和譯者等資訊。]

相關文章