As a developer, you need to be able to create systems and applications that can handle dynamic code. These programs should have the ability to manipulate variables, properties, and object methods at runtime. To this end, a new global object, Reflect
, that is capable of handling simple code manipulation, was introduced in ES6.
The goal of this article is to help you better understand the concept of Reflect
in JavaScript and how to use the various methods provided. Reflect
enables you to easily tinker with the functionality of an existing object while still providing its default behavior.
Table of Contents:
Reflect
?JavaScript Reflect
is an inbuilt ES6 global object that provides the ability to manipulate properties, variables, and object methods at runtime. It is not a constructor, therefore you cannot use the new
operator with it.
Proxy
constructor and Reflect
?Proxy
and Reflect
were both introduced in ES6 and are used for performing tasks, but they are a bit different.
Unlike Reflect
, JavaScript’s Proxy
does not have any properties. Instead, it wraps around another object and intercepts its operations. Meanwhile, Reflect
is an inbuilt object that simplifies the creation of Proxy
and makes it possible to call internal methods.
Proxy
takes only two arguments:
target
: The object that the Proxy
will wraphandler
: The Proxy
configuration that will intercept target operationsHere’s an example:
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 !
The above example is equivalent to Reflect.get()
, which is described later in this guide, however, the Reflect.get()
technique is simpler and more straightforward.
Reflect
API methodsLet’s take a closer look at the methods of the Reflect
object. All of these methods are static, i.e., they may only be used on the Reflect
object and not on any instances.
Reflect.construct()
The new
operator and Reflect.construct()
method are comparable and are similar to new target(...args)
, but with the option to choose a different prototype. Reflect.construct()
accepts three arguments:
target
: The function to be invokedargs
: An array of argumentsnewTarget
: An optional constructor whose prototype should be utilized; if it is not specified, its default value is target
Consider the following example:
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()
produces a new instance of the target
or newTarget
(if specified), which was constructed with the supplied array of arguments, args
. Before the introduction of Reflect.construct()
, we would combine constructor and prototype to create an object: Object.create()
.
Reflect.apply()
Reflect.apply()
is a simple and straightforward way to call a target function using the provided parameter. It takes in three parameters:
target
: The function to be invokedthisArgument
: The this
value is needed to invoke the target
functionargs
: An array containing the parameters with which target
should be invokedHere’s an example:
/* 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
Before Reflect.apply()
was introduced, we could use the function.prototype.apply()
method to perform a similar task, like so:
const arr = [3,5,20,3,31] const a = Function.prototype.apply.call(Math.max, undefined, arr); console.log(a) // Result: 31
Reflect.defineProperty()
To create or edit a property on an object, use the Reflect.defineProperty()
method. It returns a Boolean value that indicates whether a property was successfully defined. This method takes three parameters:
target
: The object on which the property will be definedpropertyKey
: The name of the property to create or editattributes
: The attributes of the properties that are being definedSee the following example:
const obj = {} Reflect.defineProperty(obj, 'prop', {value: 70}) console.log(obj.prop) // Result: 70
Reflect.get()
As the name implies, Reflect.get()
is used to retrieve a property from an object. It accepts three arguments:
target
: The object to be targetedpropertyKey
: The name of the property to obtainreceiver
(optional): If a getter is encountered, the this
value is passed as the receiver for the call to the target objectHere’s an example:
// 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()
The Reflect.getPrototypeOf()
function returns the prototype of the provided target, much like Object.getPrototypeOf()
. Only one argument is accepted by this method:
target
: The object of which we want to get the prototypeSee the following example:
const profile = { name: 'Pascal' }; const pro = Reflect.getPrototypeOf(profile); console.log(pro);
Reflect.set()
The Reflect.set()
method is used to assign a value to an object property. It returns true
to indicate that the property was set successfully. This function takes four arguments:
target
: The object on which the property is to be setkey
: The property’s namevalue
: The value that will be allocatedreceiver(optional)
: If a setter is found, the this
value must be used to call the targetHere’s an example:
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()
is a method for removing a property from an object. If the property is correctly deleted, it returns true
. This function takes two arguments:
target
: The objectke
y: The name of the property to be deletedSee the following example:
Reflect.deleteProperty(obj3, 'age'); console.log(obj3)
Reflect.isExtensible()
Reflect.isExtensible()
, like Object.isExtensible()
, is a method that detects if an object is extensible (i.e., whether additional properties may be added to it). Reflect.isExtensible()
returns a Boolean to indicate whether the target is extensible. It only considers one argument:
target
: The object to be checked for extensibilityThe Reflect.preventExtensions()
method may be used to prevent an object from becoming extensible i.e prevents new properties from ever being added to an object.
See the below example:
const user = { name: "John Deeman" }; console.log(Reflect.isExtensible(user)) // true // block extension Reflect.preventExtensions(user); console.log(Reflect.isExtensible(user)) // false
Reflect.ownKeys()
The Reflect.ownKeys()
method basically returns an array containing the property keys of the target object. It only considers one argument:
target
: The object from which to get the keysHere’s an example:
const obj = { car: "Rolls Royce", color: "black" }; const array1 = []; console.log(Reflect.ownKeys(obj)); // ["car", "color"] console.log(Reflect.ownKeys(array1)); // ["length"]
Reflect.getOwnPropertyDescriptor()
The Reflect.getOwnPropertyDescriptor()
method returns a descriptor that defines how a specific property on a given object is configured. It requires two parameters:
target
: The object to be searched for the propertykey
: The name of the property for which a description is requiredSee the below example:
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
A property descriptor may contain the following attributes:
value
: The value associated with the propertywritable
: A Boolean that returns true
only if the property’s associated value is modifiableconfigurable
: A Boolean that returns true
only if the property descriptor’s type may be modified and the property can be removed from the related objectenumerable
: A Boolean that returns true
only if the property appears during property enumeration on the related objectReflect.has()
The Reflect.has()
method verifies if a property is defined in the target object. It returns a boolean. Reflect.has()
performs similar operations to the in
operator and accepts two parameters:
target
: The object to which the property will be checkedkey
: The name of the property to verifyHere’s an example:
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
In this article, we examined the JavaScript Reflect
object and also discussed the difference between Proxy
and Reflect
. We also looked at examples of how to use various Reflect
methods, including Reflect.get()
for returning the value of an object property, Reflect.deleteProperty()
for deleting an object’s property, and Reflect.ownKeys()
for returning an object’s property keys.
Debugging code is always a tedious task. But the more you understand your errors, the easier it is to fix them.
LogRocket allows you to understand these errors in new and unique ways. Our frontend monitoring solution tracks user engagement with your JavaScript frontends to give you the ability to see exactly what the user did that led to an error.
LogRocket records console logs, page load times, stack traces, slow network requests/responses with headers + bodies, browser metadata, and custom logs. Understanding the impact of your JavaScript code will never be easier!
Hey there, want to help make our blog better?
Join LogRocket’s Content Advisory Board. You’ll help inform the type of content we create and get access to exclusive meetups, social accreditation, and swag.
Sign up nowCompare Prisma and Drizzle ORMs to learn their differences, strengths, and weaknesses for data access and migrations.
It’s easy for devs to default to JavaScript to fix every problem. Let’s use the RoLP to find simpler alternatives with HTML and CSS.
Learn how to manage memory leaks in Rust, avoid unsafe behavior, and use tools like weak references to ensure efficient programs.
Bypass anti-bot measures in Node.js with curl-impersonate. Learn how it mimics browsers to overcome bot detection for web scraping.