作为一名开发人员,你需要能够创建能够处理动态代码的系统和应用程序。这些程序应该有能力在运行时操纵变量、属性和对象方法。为此,一个新的全局对象。 [Reflect](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect)
,它能够处理简单的代码操作,在ES6中被引入。
本文的目的是帮助你更好地理解JavaScript中Reflect
的概念,以及如何使用所提供的各种方法。Reflect
,使你能够轻松地修补一个现有对象的功能,同时仍然提供其默认行为。
什么是JavaScriptReflect
?
JavaScriptReflect
是一个内置的ES6全局对象,提供了在运行时操作属性、变量和对象方法的能力。它不是一个构造函数,因此你不能使用 [new](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/new)
操作符。
Proxy
构造函数和Reflect
有什么区别?
Proxy
和 都是在ES6中引入的,都是用来执行任务的,但它们有一些不同。Reflect
与Reflect
不同,JavaScript的Proxy
并没有任何属性。相反,它包裹着另一个对象并拦截其操作。同时,Reflect
是一个内置的对象,它简化了Proxy
的创建,并使其能够调用内部方法。
Proxy
它只接受两个参数:
target
:Proxy
将被包裹的对象handler
:将拦截目标操作的Proxy
配置。
这里有一个例子:
const profile = { name: 'Pascal', age:23 }
const handler = {
get(target, prop, receiver) {
if (target[prop]) {
return target[prop]
}
return `"${prop}" prop don't exist on this object !`
}
}
const profileProxy = new Proxy (profile, handler)
console.log(profileProxy.name) // Pascal
console.log(profileProxy.profession) // "profession" prop don't exist on this object !
上面的例子等同于本指南后面介绍的Reflect.get()
,然而,Reflect.get()
技术更简单、更直接。
使用JavaScriptReflect
API方法
让我们仔细看一下Reflect
对象的方法。所有这些方法都是静态的,也就是说,它们只能用于Reflect
对象,不能用于任何实例。
Reflect.construct()
new
操作符和Reflect.construct()
方法具有可比性,与new target(...args)
类似,但可以选择不同的原型。Reflect.construct()
接受三个参数:
target
:要调用的函数args
:一个参数数组newTarget
:一个可选的构造函数,其原型应该被利用;如果没有指定,其默认值为target
请看下面的例子:
function summation(x,y,z){
this.add = x + y +z
}
const sum = Reflect.construct(summation, [1,2,3,4,5])
console.log(sum)
// Result: summation {add: 6}
Reflect.construct()
产生一个新的 或 (如果指定的话)的实例,该实例是用提供的参数数组 。在引入 之前,我们会结合构造函数和原型来创建一个对象: 。target
newTarget
args
Reflect.construct()
Object.create()
Reflect.apply()
Reflect.apply()
是一种简单明了的方式,使用所提供的参数调用一个目标函数。它吸收了三个参数:
target
:要调用的函数thisArgument
:this
值是需要调用target
函数的。args
:一个包含参数的数组,用于调用target
。
这里有一个例子:
/* Return the highest value in the array */
const arr = [3,5,20,3,31]
const a = Reflect.apply(Math.max, undefined, arr)
console.log(a)
// Result: 31
在引入Reflect.apply()
之前,我们可以使用function.prototype.apply()
方法来执行类似的任务,像这样:
const arr = [3,5,20,3,31]
const a = Function.prototype.apply.call(Math.max, undefined, arr);
console.log(a)
// Result: 31
Reflect.defineProperty()
要在一个对象上创建或编辑一个属性,使用Reflect.defineProperty()
方法。它返回一个布尔值,表示一个属性是否被成功定义。这个方法需要三个参数:
target
:将被定义属性的对象propertyKey
:要创建或编辑的属性的名称attributes
:被定义的属性的属性
请看下面的例子:
const obj = {}
Reflect.defineProperty(obj, 'prop', {value: 70})
console.log(obj.prop)
// Result: 70
Reflect.get()
顾名思义,Reflect.get()
是用来从一个对象中检索一个属性。它接受三个参数:
target
:被定位的对象propertyKey
:要获取的属性的名称receiver
(可选)。如果遇到一个获取器, ,作为调用目标对象的接收者,被传递给目标对象this
这里有一个例子:
// with array
const b = [10,11,12,13,14]
console.log(Reflect.get(b, 2))
// Result: 12
// with object
const obj = {name: "Pascal", age: 23}
console.log(Reflect.get(obj, 'age'))
// Result: 23
Reflect.getPrototypeOf()
Reflect.getPrototypeOf()
函数返回所提供的目标的原型,很像Object.getPrototypeOf()
。这个方法只接受一个参数:
target
:我们想获得原型的对象
请看下面的例子:
const profile = {
name: 'Pascal'
};
const pro = Reflect.getPrototypeOf(profile);
console.log(pro);
Reflect.set()
Reflect.set()
方法是用来给一个对象属性赋值的。它返回true
,表示该属性被成功设置。这个函数需要四个参数:
target
:要设置该属性的对象key
:属性的名称value
:将被分配的值receiver(optional)
:如果找到一个设置器,必须使用this
值来调用目标。
这里有一个例子:
const arr1 = [];
Reflect.set(arr1, 0, 'first');
Reflect.set(arr1, 1, 'second');
Reflect.set(arr1, 2, 'third');
console.log(arr1);
Reflect.deleteProperty()
Reflect.delete Property()
是一个从一个对象中删除一个属性的方法。如果该属性被正确删除,它将返回 。这个函数需要两个参数。true
:
target
:对象ke
y:要删除的属性的名称
请看下面的例子:
Reflect.deleteProperty(obj3, 'age');
console.log(obj3)
Reflect.isExtensible()
Reflect.isExtensible()
Reflect.isExtensible()
,像 ,是一个检测对象是否可扩展的方法(即,是否可以向其添加额外的属性)。 返回一个布尔值,表示目标是否可扩展。它只考虑一个参数。Object.isExtensible()
target
:要检查的对象的可扩展性
Reflect.preventExtensions()
方法可以用来防止一个对象成为可扩展的,即防止新的属性被添加到一个对象。
请看下面的例子:
const user = {
name: "John Deeman"
};
console.log(Reflect.isExtensible(user))
// true
// block extension
Reflect.preventExtensions(user);
console.log(Reflect.isExtensible(user))
// false
Reflect.ownKeys()
Reflect.ownKeys()
方法基本上返回一个包含目标对象的属性键的数组。它只考虑一个参数。
target
:要获取键值的对象
这里有一个例子:
const obj = {
car: "Rolls Royce",
color: "black"
};
const array1 = [];
console.log(Reflect.ownKeys(obj));
// ["car", "color"]
console.log(Reflect.ownKeys(array1));
// ["length"]
Reflect.getOwnPropertyDescriptor()
Reflect.getOwnPropertyDescriptor()
方法返回一个描述符,该描述符定义了一个给定对象上的特定属性是如何配置的。它需要两个参数:
target
:要搜索该属性的对象key
:需要描述的属性的名称
请看下面的例子:
const obj = {
car: "Rolls Royce",
color: "black",
get (){
return `I have a ${color} ${car} car`
}
};
console.log(Reflect.getOwnPropertyDescriptor(obj, 'car').value);
// "Rolls Royce"
console.log(Reflect.getOwnPropertyDescriptor(obj, 'color'));
// {value: "black", writable: true, enumerable: true, configurable: true}
console.log(Reflect.getOwnPropertyDescriptor(obj, 'color').writable);
// true
一个属性描述器可以包含以下属性:
value
:与该属性相关的值writable
:一个布尔值,只有当属性的关联值可以修改时才返回true
。configurable
:一个布尔值,仅在属性描述符的类型可被修改且该属性可从相关对象中删除时返回true
。enumerable
:一个布尔值,仅在该属性出现在相关对象的属性枚举过程中时返回true
。
Reflect.has()
Reflect.has()
方法验证一个属性是否在目标对象中被定义。它返回一个布尔值。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
结论
在这篇文章中,我们研究了JavaScript的Reflect
对象,还讨论了Proxy
和Reflect
的区别。我们还看了如何使用各种Reflect
方法的例子,包括用于返回对象属性值的Reflect.get()
,用于删除对象属性的Reflect.deleteProperty()
,以及用于返回对象的属性键的Reflect.ownKeys()
。