ECMAScript 6 之Reflect

1. 概述

Reflect對象與Proxy對象一樣,也是 ES6 爲了操作對象而提供的新 API。

Reflect不是一個函數對象,它是不可構造的,而且Reflect的所有屬性和方法都是靜態的。

Reflect對象的設計目的有這樣幾個:

  • Object對象的一些明顯屬於語言內部的方法,放到Reflect對象上
  • 修改某些Object方法的返回結果,讓其變得更合理
  • Object操作都變成函數行爲
  • Reflect對象的方法與Proxy對象的方法一一對應,只要是Proxy對象的方法,就能在Reflect對象上找到對應的方法。能夠讓Proxy對象調用對應的Reflect方法,完成默認行爲,作爲修改行爲的基礎。
var person = {
	name: "jidi"
}

var proxy = new Proxy(person, {
	set(target, property, value, receiver) {
		return Reflect.set(target, property, value, receiver);
	}
})

person; // {name: "jidi"}
proxy.name = 1;
person; // {name: 1}

上面代碼中,代理攔截對person對象屬性的寫入行爲,使用Reflect.set方法確保能夠正常寫入屬性。

2. Reflect對象靜態方法

Reflect對象一共有 13 個靜態方法,它們都是跟Proxy對象攔截操作是一一對應的。

  • Reflect.apply(target, thisArg, argumentsList)
  • Reflect.construct(target, argumentsList)
  • Reflect.get(target, property, receiver)
  • Reflect.set(target, property, value, receiver)
  • Reflect.defineProperty(target, property, descriptor)
  • Reflect.deleteProperty(target, property)
  • Reflect.has(target, property)
  • Reflect.ownKeys(target)
  • Reflect.isExtensible(target)
  • Reflect.preventExtensions(target)
  • Reflect.getOwnPropertyDescriptor(target, property)
  • Reflect.getPrototypeOf(target)
  • Reflect.setPrototypeOf(target, prototype)

2.1 Reflect.get()

Reflect.get方法可以從一個對象中取屬性值。就如同屬性訪問器,但卻是通過函數調用來實現。

語法

Reflect.get(target, property[, receiver])

參數
以下是傳遞給get方法的參數:

  • target:目標對象
  • property:屬性名
  • receiver:如果target對象中指定了getterreceiver則爲getter調用時的this

返回值
返回目標對象對應屬性的值。如果該屬性不存在,返回undefined

約束
如果目標值(target)類型不是Object,拋出一個 TypeError

示例一

var person = {
	name: "jidi",
	age: 22
}

Reflect.get(person, "name"); // "jidi"
Reflect.get(person, "sex"); // undefined

示例二

var perosn = {
	name: "jidi",
	age: 22,
	get info() { // 定義getter
		return this.name + this.age;
	}	
}

var receiver = {
	name: "基地",
	age: 23
}

Reflect.get(person, "info", receiver); // "基地23" 

上面代碼演示了第三個參數receiver的使用。

示例三

Reflect.get(true, 'toString'); // Uncaught TypeError: Reflect.get called on non-object at Object.get

上面代碼演示了違反約束的情況。

2.2 Reflect.set()

Reflect.set 方法允許給對象屬性賦值並且是以函數的方式。

語法

Reflect.set(target, property, value[, receiver]);

參數
以下是傳遞給set方法的參數:

  • target:設置屬性的目標對象
  • property:設置的屬性的名稱
  • value:設置的值
  • receiver:如果遇到 setterreceiver則爲setter調用時的this值。

返回值
返回一個布爾值,表示屬性是否設置成功。

約束
如果target不是一個對象,會報錯TypeError

示例一

var person = {};

Reflect.set(person, "name", "jidi");
person.name; // "jidi"

示例二

var person = {
	name: "jidi",
	age: 22,
	set info(value) {
		 console.info(this === receiver)
		this.name = value;
	}
};

var receiver = {
	name: "基地"
}

Reflect.set(person, "info", "jidi", receiver); // true
receiver.name; // "jidi"

上面代碼,person對象設置了setter,當調用setter時,setter內部this會指向receiver

示例三

Reflect.set(1, 'name', {}) // Uncaught TypeError: Reflect.set called on non-object at Object.set

上面代碼演示了違反約束的情況。

2.3 Reflect.has()

Reflect.has用於檢查一個對象是否擁有某個屬性, 相當於in 操作符 ,但是是以函數的形式。

語法

Reflect.has(target, property);

參數
以下是傳遞給has方法的參數:

  • target:目標對象
  • property:屬性名

返回值
返回一個布爾值,表示對象是否擁有某個屬性。

約束
如果目標對象並非Object 類型,拋出TypeError

示例

var person = {
	name: "jidi"
}

Reflect.has(person, "name"); // true
Reflect.has(person, "age"); // false

2.4 Reflect.deleteProperty()

Reflect.deleteProperty用於刪除對象屬性,相當於delete obj[property]

語法

Reflect.deleteProperty(target, property);

參數
以下是傳遞給deleteProperty方法的參數:

  • target:目標對象
  • property:屬性名

返回值
返回一個布爾值,表示對象屬性是否被刪除。

約束
如果目標對象並非Object 類型,拋出TypeError

示例

var person = {
	name: "jidi",
	age: 22
}

Reflect.deleteProperty(person, 'name'); // true
person; // {age: 22}

// 如果屬性不存在,返回 true
Reflect.deleteProperty({}, "name"); // true

2.5 Reflect.construct()

Reflect.construct方法等同於new target(...args),這提供了一種不使用new,來調用構造函數的方法。

語法

Reflect.construct(target, argumentsList[, newTarget]);

參數
以下是傳遞給construct方法的參數:

  • target:被運行的目標構造函數
  • argumentsList:目標構造函數調用時的參數
  • newTarget :新創建對象的原型對象, 默認值爲target

返回值
返回一個實例對象。

約束
如果target或者newTarget不是構造函數,拋出TypeError異常。

示例

// 定義構造函數
function Person(name, sex, age) {
	if(!new.target) {
		return new Person(name, sex, age);
	}
	this.name = name;
	this.sex = sex;
	this.age = age
}

// 使用new命令寫法
var p1 = new Person("jidi", "男", 22);
p1; // Person {name: "jidi", sex: "男", age: 22}

// 使用Reflect.construct()靜態方法
var p2 = Reflect.construct(Person, ["基地", "男", 23]);
p2; // Person {name: "jidi", sex: "男", age: 22}

2.6 Reflect.getPrototypeOf()

Reflect.getPrototypeOf 返回指定對象的原型 (即內部的 [[Prototype]] 屬性的值) 。

語法

Reflect.getPrototypeOf(target);

參數
以下是傳遞給getPrototypeOf方法的參數:

  • target:目標對象

返回值
給定對象的原型。如果給定對象沒有繼承的屬性,則返回 null

約束
如果 target 不是 Object,拋出一個 TypeError 異常。

演示

var person = { // 普通對象 
	name:"jidi"
}

var proto = { // 原型對象
	sleep() {
		console.info("sleeping....")
	}
}

// 設置原型對象
Object.setPrototypeOf(person,proto);

Reflect.getPrototypeOf(person) === proto; // true

2.7 Reflect.setPrototypeOf()

Reflect.setPrototypeOf 方法改變指定對象的原型。

語法

Reflect.setPrototypeOf(target, prototype);

參數
以下是傳遞給setPrototypeOf方法的參數:

  • target:設置原型的目標對象
  • prototype:對象的新原型(一個對象或 null

返回值
返回一個 Boolean 值表明原型是否已經成功設置。

約束
如果target 不是Object ,或 prototype 既不是對象也不是 null,拋出一個 TypeError異常。

示例

var person = {};

// 設置原型,成功返回true
Reflect.setPrototypeOf(person , Array.prototype); // true

person.length; // 0

// target不能爲null或undefined
Object.setPrototypeOf(null, {}); // Uncaught TypeError: Object.setPrototypeOf called on null or undefined at Function.setPrototypeOf 

2.8 Reflect.apply()

靜態方法 Reflect.apply()通過指定的參數列表發起對目標(target)函數的調用。

語法

Reflect.apply(target, thisArgument, argumentsList);

參數
以下是傳遞給apply方法的參數:

  • target:目標函數
  • thisArgument:target函數調用時綁定的this對象。
  • argumentsList:target函數調用時傳入的實參列表,該參數應該是一個類數組的對象。

返回值
返回值是調用完帶着指定參數和this 值的給定的函數後返回的結果。

約束
如果 target對象不可調用,拋出 TypeError

示例

// 舊寫法
Function.prototype.apply.call(Math.floor, Math, [1.23]); // 1
// 或者
Math.floor.apply(Math, [1.23]); // 1

// 新寫法
Reflect.apply(Math.floor, Math, [1.23]); // 1

2.9 Reflect.defineProperty()

靜態方法 Reflect.defineProperty()基本等同於 Object.defineProperty()方法,唯一不同是返回 Boolean值。

語法

Reflect.defineProperty(target, property, attributes)

參數
以下是傳遞給defineProperty方法的參數:

  • target:目標對象
  • property:要定義或修改的屬性的名稱
  • attributes:要定義或修改的屬性的描述

返回值
返回Boolean值,表示屬性是否被成功定義。

約束
如果target不是 Object,拋出一個 TypeError

示例

var person = {};

// 設置對象屬性
Reflect.defineProperty(person, "name", {
	value: "jidi",
	enumerable: true
})

person; // {name: "jidi"}

Object.getOwnPropertyDescriptor(person, "name"); // {value: "jidi", writable: false, enumerable: true, configurable: false}

2.10 Reflect.getOwnPropertyDescriptor()

Reflect.getOwnPropertyDescriptor基本等同於Object.getOwnPropertyDescriptor,用於得到指定屬性的描述對象。

語法

Reflect.getOwnPropertyDescriptor(target, property);

參數

  • target:需要尋找屬性的目標對象
  • property:獲取自己的屬性描述符的屬性的名稱。

返回值
如果屬性存在於給定的目標對象中,則返回屬性描述對象;否則,返回 undefined

約束
如果目標對象不是 Object,拋出一個 TypeError

示例

var person = {
	name: "jidi"
}

Reflect.getOwnPropertyDescriptor(person, "name"); // {value: "jidi", writable: false, enumerable: true, configurable: false}

2.11 Reflect.isExtensible ()

Reflect.isExtensible方法對應Object.isExtensible,返回一個布爾值,表示當前對象是否可擴展。

語法

Reflect.isExtensible(target);

參數

  • target:檢查是否可擴展的目標對象。

返回值
返回一個Boolean 值表明該對象是否可擴展。

約束
如果目標對象不是 Object,拋出一個 TypeError

示例

var p= {};
Reflect.isExtensible(p); // true 

Reflect.preventExtensions(p); 

Reflect.isExtensible(p); // false 

2.12 Reflect.preventExtensions()

Reflect.preventExtensions對應Object.preventExtensions方法,用於讓一個對象變爲不可擴展。它返回一個布爾值,表示是否操作成功。

語法

Reflect.preventExtensions(target);

參數

  • target:阻止擴展的目標對象。

返回值
返回一個Boolean 值表明目標對象是否成功被設置爲不可擴展。

約束
如果目標對象不是 Object,拋出一個 TypeError

示例

var p= {};
Reflect.isExtensible(p); // true 

Reflect.preventExtensions(p); 

Reflect.isExtensible(p); // false 

2.13 Reflect.ownKeys ()

Reflect.ownKeys方法用於返回一個由目標對象自身的屬性組成的數組。

語法

Reflect.ownKeys(target)

參數

  • target:獲取自身屬性的目標對象。

返回值
由目標對象的自身屬性組成的數組。

約束
如果目標對象不是 Object,拋出一個 TypeError

示例

var person= {
  name: "jidi",
  age: 22,
  [Symbol.for('x')]: 3,
  [Symbol.for('y')]: 4,
};

Reflect.ownKeys(person); // ["name", "age", Symbol(x), Symbol(y)]

3 參考鏈接

本篇博文是我自己學習筆記,原文請參考:ECMAScript 6 入門MDN網站
如有問題,請及時指出!
歡迎溝通交流,郵箱:[email protected]

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章