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]

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