A Time of REFLECTion for Objects in JavaScript
When ECMAScript6 (ES6) was released back in 2015, it provided many enhancements to the JavaScript language, and added many more features intended to make large-scale software development easier. In my journey for a deeper understanding of JavaScript, I stumbled across an improvement from ES6 that peaked my interest and I decided to write about, the Reflect Object!
Introduction
Reflect is an object that defines a convenient collection of related functions, all in a single namespace, that mimic the behavior of core language syntax and duplicate features of various preexisting Object functions. However, unlike the Math object, it is NOT a class. The functions for Reflect that were added in ES6, define an API for “reflecting upon” objects and their properties. Although the functions of Reflect don’t provide any new features, they have been grouped together in one convenient API. I wanted to create a page where all of the functions were located in one spot. Let me take you through all the functions that the Reflect API encompass.
Reflect API functions
- Reflect.apply(function, object, [args]): The Reflect.apply function invokes the target function, function as a method of the object and passes the values in the args array as arguments.
- Reflect.construct(constructor, [args], newTarget): The construct function invokes the constructor as if the new keyword had been used and passes the elements of the array args as arguments. The newTarget argument is optional, but if specified, it is used as the value of new.target within the constructor invocation. If not specified, the new.target value will default to the constructor.
- Reflect.defineProperty(object, name, descriptor): This function defines a property on the object, using name (string/symbol) as the name of the property. The descriptor object should define the value and attributes of the property. The function will return true on success and false on failures.
- Reflect.deleteProperty(object, name): This function deletes the property with the specified name (string/symbol) from the object. The function will return true if the property has been deleted and false if the property could not be deleted.
- Reflect.get(object, name, receiver): The get function returns the value of the property of the object with the specified name (string/symbol). The receiver argument is usually specified when the property is an accessor method with a getter. Then the getter function is called as a method of the receiver instead of a method of the object.
- Reflect.getOwnPropertyDescriptor(object, name): This function defines a property on the object, using name (string/symbol) as the name of the property. The descriptor object should define the value and attributes of the property. The function will return true on success and false on failures.
- Reflect.getPrototypeOf(object): This function will return the prototype of the object or null if the object has no prototype. It will give a TypeError if the object is a primitive value instead of an object.
- Reflect.has(object, name): This function will return true if the object has a property with the specified name (string/symbol).
- Reflect.isExtensible(object): This function will return true if the object is extensible (the ability of an object to add new properties) and false if it is not.
- Reflect.ownKeys(object): This function will return an array of the names of the properties for the object. It will give a TypeError if the object is not an object.
- Reflect.preventExtensions(object): This function sets the extensible attribute of the object to false and returns true to indicate successful execution. It will give a TypeError if the object is not an object.
- Reflect.set(object, name, value, receiver): This function will set the property with the specified name of the object to the specified value. It will return true on success and false on failure. The receiver is an optional argument that will be used if the specified property is an accessor property with a setter function. Then the setter will be invoked as a method of the receiver instead of being invoked as a method of the object.
- Reflect.setPrototypeOf(object, prototype): This function will set the prototype of the object to the prototype. It will return true if the function is executed successfully and false if not.
Why Is It Important?
The Reflect object is a very useful tool that allows users to manipulate variables, properties, and methods in an object. The Reflect API is important because it allows users to develop programs and frameworks that are able to handle dynamic code.
Additionally, Reflect simplifies the creation of Proxy. A proxy is an object that wraps another object and intercepts operations, optionally handling them on its own, or transparently allowing the object to handle them. It essentially allows users a way to write code that alters the fundamental behavior of JavaScript objects.
Reflect allows the user to to call operators (new, delete, …) as functions. But most importantly, best stated by javascript.info, “for every internal method, trappable by Proxy
, there’s a corresponding method in Reflect
, with the same name and arguments as the Proxy
trap.” Thus Reflect can be used to forward an operation to the original object.
Conclusion
Hopefully you can use this article as a reference point for Reflect functions. They can be useful and work in conjunction with proxies. It can be a very useful tool when working with proxies and a really nifty group of functions that help when manipulating objects. This article is just scratching the surface of its potential, especially with proxies. As usual, I challenge you to dive deeper into this topic and I will include some additional resources below, to help you in your research.