- Reflect是一个内置的对象,它提供拦截JavaScript操作的方法,是
ES6
为了操作对象而提供的新API。 - Reflect不是一个函数对象,因此它是
不可构造
的 - Reflect的所有属性和方法都是
静态的
- Reflect的操作是
函数式
的
存在意义
- 调用对象的基本方法
- 修改某些Object方法的返回结果,让其变得更规范化
- Reflect对象的方法与
Proxy
对象的方法一一对应,只要是Proxy
对象的方法,即能在Reflect
对象上找到对应的方法
Object的缺陷
书写不规范可能导致不可预估的错误
在
Object.defineProperty
上对一个不可写
或不可枚举
的属性进行getter
或setter
时会抛出错误,对于这个错误,我们需要try catch
去捕获,而Reflect.defineProperty则会抛出false
,表示本次操作失败(Reflect对对象的操作都会抛出true和false来表示是否操作成功)
- Object
const obj = {
name: "ray",
};
Object.defineProperty(obj, "age", {
value: 30,
writable: true, //只读
configurable: false, // 不可删除和修改
});
Object.defineProperty(obj, "age", {
get() {
return;
},
});
console.log(obj.age);
/**
* Uncaught TypeError: Cannot redefine property: age(无法重新定义:age)
at Function.defineProperty (<anonymous>)
at <anonymous>
*/
- Reflect
const obj = {
name: "ray",
};
Object.defineProperty(obj, "age", {
value: 30,
writable: true, //只读
configurable: false, // 不可删除和修改
});
const age = Reflect.defineProperty(obj, "age", {
get() {
return;
},
});
console.log(age); // false
console.log(obj.age); // 30
无法准确读取对象的所有属性
在
Object.defineProperty
上设置一个不可枚举
的属性或者这个属性的key为Symbol
类型时,使用Object.keys、Object.values
无法读取对应的key、value
- Object
const obj = {
name: "ray",
[Symbol("job")]:"Frontend"
};
Object.defineProperty(obj, "age", {
value: 30,
enumerable: false, //不可枚举
});
console.log(Object.keys(obj));
// ['name']
console.log(Object.values(obj));
// ['ray']
- Reflect
const obj = {
name: ()=>{
return "ray"
},
[Symbol("job")]:"Frontend"
};
Object.defineProperty(obj, "age", {
value: 30,
enumerable: false, //不可枚举
});
console.log(Reflect.ownKeys(obj));
// ['name', 'age', Symbol(job)]
无法修改this
- Object
const obj = {
a: 1,
b: 2,
get c() {
return this.a + this.b;
},
};
console.log(obj.c); // 3
const obj1 = {
a: 3,
b: 4,
};
obj.a = obj1.a;
obj.b = obj1.b;
console.log(obj.c); // 7
上面的代码其实我们想要得到obj1
中a
和b
的相加之和,而因为无法修改this
,因此不得不如此处理
- Reflect
const obj = {
a: 1,
b: 2,
get c() {
return this.a + this.b;
},
};
console.log(obj.c); // 3
const obj1 = {
a: 3,
b: 4,
};
console.log(Reflect.get(obj, "c", obj1)); // 7
我们看一个相对复杂的例子
const obj = {
a: 1,
b: 2,
get c() {
return this.a + this.b;
},
};
const p = new Proxy(obj, {
get(target, key) {
console.log(key);
return target[key];
},
});
const p1 = new Proxy(obj, {
get(target, key, receiver) {
console.log(key);
return Reflect.get(target, key, receiver);
},
});
console.log(p.a);
// a
// 1
console.log(p.b);
// b
// 2
console.log(p.c);
// c
// 3
console.log(p1.a);
// a
// 1
console.log(p1.b);
// b
// 2
console.log(p1.c);
// c
// a
// b
// 2
Reflect的一些常用方法
Reflect.get(target,name,receiver)
Reglect.get()有三个参数,分别是:
- target:目标对象
- key:对象属性
- receiver:代理对象(可忽略)。作用:查找并返回
target
对象的key
的value
,如果该属性不存在则返回undefined
const obj = {
name: "ray"
};
console.log(Reflect.get(obj,"name"))
// ray
Reflect.set(target, name, value, receiver)
用于设置target
对象的key
的value
,如果修改成功返回true
,失败返回false
const obj = {
name: "ray"
};
const job = Reflect.set(obj,'job',"Frontend")
console.log(job)
// true
console.log(obj)
// { name: 'ray', job: 'Frontend' }
Reflect.has(target, key)
用于判断当前key
在目标target
内是否存在,如果存在返回true
,否则返回false
const obj = {
name: "ray"
};
console.log("name" in obj)
// true
console.log(Object.prototype.hasOwnProperty.call(obj,"name"))
// true
console.log(Reflect.has(obj,"name"))
// true
Reflect.deleteProperty(target, key)
用于删除taget
中的key
属性
const obj = {
name: "ray",
age: 32,
job: "Frontend",
};
delete obj.age;
console.log(obj);
// { name: 'ray', job: 'Frontend' }
Reflect.deleteProperty(obj, "job");
console.log(obj);
// { name: 'ray' }
Reflect.ownKeys (target)
用于返回目标对象的所有属性,包含Symbol
const obj = {
name: ()=>{
return "ray"
},
[Symbol("job")]:"Frontend"
};
Object.defineProperty(obj, "age", {
value: 30,
enumerable: false, //不可枚举
});
console.log(Reflect.ownKeys(obj));
// ['name', 'age', Symbol(job)]
Reflect对象一共有
13
个静态方法,下表详细介绍了Object
和Reflect
API上可用方法之间的差异。请注意,如果API中不存在某种方法,则将其标记为N/A
方法 | Object | Reflect |
---|---|---|
defineProperty() | Object.defineProperty() 返回传递给函数的对象。如果未在对象上成功定义属性,则返回TypeError。 | 如果在对象上定义了属性,则Reflect.defineProperty()返回true,否则返回false。 |
defineProperties() | Object.defineProperties() 返回传递给函数的对象。如果未在对象上成功定义属性,则返回TypeError。 | N/A |
set() | N/A | 如果在对象上成功设置了属性,则Reflect.set()返回true,否则返回false。如果目标不是Object,则抛出TypeError |
get() | N/A | Reflect.get()返回属性的值。如果目标不是Object,则抛出TypeError。 |
getOwnPropertyDescriptor() | 如果传入的对象参数上存在Object.getOwnPropertyDescriptor() ,则会返回给定属性的属性描述符,如果不存在,则返回undefined。 | 如果给定属性存在于对象上,则Reflect.getOwnPropertyDescriptor() 返回给定属性的属性描述符。如果不存在则返回undefined,如果传入除对象(原始值)以外的任何东西作为第一个参数,则返回TypeError |
getOwnPropertyDescriptors() | Object.getOwnPropertyDescriptors() 返回一个对象,其中包含每个传入对象的属性描述符。如果传入的对象没有拥有的属性描述符,则返回一个空对象。 | N/A |
getPrototypeOf() | Object.getPrototypeOf()返回给定对象的原型。如果没有继承的原型,则返回null。在 ES5 中为非对象抛出TypeError,但在 ES2015 中强制为非对象。 | Reflect.getPrototypeOf()返回给定对象的原型。如果没有继承的原型,则返回 null,并为非对象抛出TypeError。 |
setPrototypeOf() | 如果对象的原型设置成功,则Object.setPrototypeOf()返回对象本身。如果设置的原型不是Object或null,或者被修改的对象的原型不可扩展,则抛出TypeError。 | 如果在对象上成功设置了原型,则Reflect.setPrototypeOf() 返回 true,否则返回 false(包括原型是否不可扩展)。如果传入的目标不是Object,或者设置的原型不是Object或null,则抛出TypeError。 |
isExtensible() | 如果对象是可扩展的,则 Object.isExtensible()返回 true,否则返回 false。如果第一个参数不是对象(原始值),则在 ES5 中抛出TypeError。在 ES2015 中,它将被强制为不可扩展的普通对象并返回false。 | 如果对象是可扩展的,则Reflect.isExtensible() 返回true,否则返回false。如果第一个参数不是对象(原始值),则抛出TypeError。 |
preventExtensions() | Object.preventExtensions() 返回被设为不可扩展的对象。如果参数不是对象(为原始值),则在 ES5 中抛出 TypeError。在 ES2015 中,则将参数视为不可扩展的普通对象,并返回对象本身。 | 如果对象已变得不可扩展,则 Reflect.preventExtensions() 返回 true,否则返回 false。如果参数不是对象(为原始值),则抛出 TypeError。 |
keys() | Object.keys()返回一个字符串数组,该字符串映射到目标对象自己的(可枚举)属性键。如果目标不是对象,则在 ES5 中抛出TypeError,但将非对象目标强制为 ES2015 中的对象 | N/A |
ownKeys() | N/A | Reflect.ownKeys()返回一个属性名称数组,该属性名称映射到目标对象自己的属性键。如果目标不是Object,则抛出TypeError。 |
deleteProperty() | N/A | 如果属性从对象中删除,则Reflect.deleteProperty()返回true,否则返回false。 |
values() | Object.values()返回一个字符串数组,该字符串映射到目标对象自己的(可枚举)属性的值。如果目标不是对象,则在 ES5 中抛出TypeError,但将非对象目标强制为 ES2015 中的对 | N/A |
apply() | N/A | 通过指定的参数列表发起对目标 (target) 函数的调用 |
construct() | N/A | Reflect.construct() 方法的行为有点像 new 操作符 构造函数,相当于运行 new target(…args)。 |
has() | N/A | 用于判断当前key在目标target内是否存在,如果存在返回true,否则返回false |