Reflect API:每個 JavaScript 開發人員都需要的瑞士軍刀

CodeForBetter發表於2023-11-22

前言

您是否曾經希望擁有一個神奇的工具包,可以讓您像超級英雄一樣控制 JavaScript 物件?向ReflectAPI 打個招呼吧,它是 ES6 中引入的一個新的全域性物件 ,它能夠處理簡單的程式碼操作。它是每個現代 JavaScript 開發人員都需要的瑞士軍刀!?

本文的目標是幫助您更好地理解 JavaScript 中的概念以及如何使用Reflect提供的各種方法。還會為您提供Reflect動手示例和實用技巧!?

什麼是 JavaScript Reflect?

Reflect是一個內建的 ES6 全域性物件,它提供了在執行時操作屬性、變數和物件方法的能力。它不是建構函式,因此不能將new運算子與它一起使用。

?Reflect 的核心目標

  1. 內省:Reflect API 提供了一套功能強大的靜態方法,使開發人員可以更好地操作和檢查 JavaScript 物件,例如檢查物件的屬性是否存在、檢索屬性描述符等。。

  2. 操作:將其視為Reflect用於物件操作的瑞士軍刀。您可以輕鬆地新增、刪除或修改物件屬性,甚至捕獲或監視這些操作。

  3. 可擴充套件性:ReflectAPI 可以被視為基礎層,它為建立 Proxy 物件奠定了基礎,使您能夠為基本操作(如屬性查詢、賦值、列舉等)構建自定義行為。

? Reflect的一些靜態方法

下面讓我們仔細看看該Reflect物件的方法。所有這些方法都是靜態的,即它們只能在Reflect物件上使用,而不能在任何例項上使用。

1.Reflect.apply()

忘記複雜的Function.prototype.apply()!使用Reflect.apply()方法可以用於呼叫函式,可以使呼叫函式變得輕而易舉。

const numbers = [1, 2, 3];
const sum = (a, b, c) => a + b + c;

// 使用 Reflect.apply()
const result = Reflect.apply(sum, null, numbers);

// 之前的用法
const result = Function.prototype.apply.call.apply(sum, null, numbers);

console.log(result); // 輸出: 6

2.Reflect.get()

厭倦了普通屬性檢索的侷限性?Reflect.get()提供更多的控制和靈活性。

const obj = { x: 42, y: 'hello' };

// 使用 Reflect.get()
const value = Reflect.get(obj, 'x');
console.log(value); // 輸出: 42

// 陣列同樣適用
const array = [10,11,12,13,14]
console.log(Reflect.get(array, 2))  // 輸出: 12

3.Reflect.set()

即使在複雜的物件層次結構中,也可以精確地修改屬性。

const obj = { x: 42 };

// 使用 Reflect.set()
Reflect.set(obj, 'x', 13);
console.log(obj.x); // 輸出: 13

// 也適用於陣列
const arr1 = []
Reflect.set(arr1, 0, 'first')
Reflect.set(arr1, 1, 'second')
Reflect.set(arr1, 2, 'third')
console.log(arr1); // 輸出: [ 'first', 'second', 'third' ]

4.Reflect.defineProperty()

建立或編輯物件的屬性從未如此簡單!

const obj = {};

// 使用 Reflect.defineProperty()
Reflect.defineProperty(obj, 'x', { value: 42, writable: false });

console.log(obj.x); // 輸出: 42

5.Reflect.deleteProperty()

將屬性從物件中刪除,就好像它們從未存在過一樣。類似物件中的delete。

const obj = { x: 42, b:43 };

// 使用 Reflect.deleteProperty()
Reflect.deleteProperty(obj, 'x');

console.log('x' in obj); // 輸出: false

6.Reflect.ownKeys()

發現物件擁有的所有鍵,包括symbol!

const obj = { x: 42, [Symbol('key')]: 'symbolValue' };

// 使用 Reflect.ownKeys()
const keys = Reflect.ownKeys(obj);

console.log(keys); // 輸出: ['x', Symbol(key)]
console.log(keys.includes('x')) // 輸出: true

7.Reflect.has()

該方法驗證目標物件中是否定義了屬性。它返回一個布林值。執行與in運算子類似的操作並接受兩個引數:

  • target: 將檢查屬性的物件
  • key: 要驗證的屬性名稱
const obj = {
  name: "Douglas"
};

console.log(Reflect.has(obj, 'name')); // true

console.log(Reflect.has(obj, 'age')); // false

console.log(Reflect.has(obj, 'toString')); // true

?為什麼使用反射?

Reflect現在,您可能會問自己:“既然有其他方法可以操作和檢查 JavaScript 物件,為什麼我還要深入研究呢?” 好問題!Reflect讓我們來揭開 JavaScript 武器庫中成為強大工具的原因。

1.函式正規化

Reflect提供了包含函數語言程式設計範例的靜態方法,使它們成為您可以在程式碼中傳遞的一等公民。

?示例:假設您想讓屬性檢索變得通用。您可以輕鬆做到這一點。

const genericGet = Reflect.get;
const value = genericGet(someObject, 'someProperty');

2.增強的錯誤處理

Reflect方法返回一個布林值來指示成功或失敗,從而允許更優雅的錯誤處理。

?示例:使用Reflect.set(),您可以檢查屬性是否已成功設定並進行相應操作。

// 使用 Reflect.deleteProperty()
const obj = {};

if (Reflect.set(obj, 'key', 'value')) {
  console.log('successfully set') // 輸出: successfully set
} else {
  console.log('failed to set') 
}
// 凍結該物件
Object.freeze(obj)

if (Reflect.set(obj, 'key', 'value')) {
  console.log('successfully set') 
} else {
  console.log('failed to set') // 輸出: failed to set
}

3.代理

Reflect完美匹配Proxy,允許無縫且直接的自定義行為。

?示例:建立日誌代理變得異常簡單。

const handler = {
    get(target, key) {
        console.log(`Reading property: ${key}`);
        return Reflect.get(target, key);
    }
};
const proxy = new Proxy(someObject, handler);

4.一致性和可預測性

Reflect中的方法提供了更加一致的 API。它們總是返回值(通常是布林值)而不是丟擲錯誤,並且引數順序是可預測的,從而使程式碼更乾淨、更易於維護。

?示例:Reflect.get()和Reflect.set()都具有一致的引數順序:target, propertyKey[, receiver]。

Reflect.get(target, property);
Reflect.set(target, property, value);

5.面向未來

隨著 JavaScript 的發展,新方法更有可能被新增到 Reflect中,這使其成為長期專案的明智選擇。

結論

在本文中我們講解了Reflect的相關概念與場景用法,相信大家在 JavaScript 中對於如何操作物件又有了全新的認知!?

相關文章