What is concept of reflection in JavaScript?

Viewed 3873

Can anyone explain how does it (reflection and build-in Reflect object) work in JS in human language and with simple examples.

Wikipedia: "In computer science, reflection is the ability of a computer program to examine, introspect, and modify its own structure and behavior at runtime".

2 Answers

reflection is a part of metaprogramming.

Metaprogramming is a programming technique in which computer programs have the ability to treat programs as their data. It means that a program can be designed to read, generate, analyse or transform other programs, and even modify itself while running.

so concept of reflection is that, just like we see our reflection in the mirror: we can see things we couldnt see without it, such as: our hair, our lips, tongue, etc.

in short, if a method or a class call this reflection stuff, it can see objects outside its knowledge, such as: instance variables, list of methods the class has, and other properties, what class called this method.

this is useful when we do metaprogramming. as method or class should be aware of things outside their (or even writer's) knowledge.

concrete example: lets say water and a cup. if you want to program water physics to fit cup, there are many ways. lets say you work with 100 other developers and have no idea what kind of container they would come up with (and someone might end up with a lake or even river) and you choose metaprogramming style. you have class water, and class cup. your water class has to be aware of properties of cup such as: max volume, weight, curves, or even max/min temperature.

result: you wont have to insert those informations as parameters whenever someone call class water as it might be difficult to track if they are growing in number.

(im not sure if that is a good enough example and explanation, so please comment a better one if it happen to cross your mind)

What is a reflection ?

  • An object can look at itself, listing and changing its properties and methods.
  • So a JavaScript object has the ability to look at its own properties and methods.
  • Reflection means examining the structure of a program and its data.
  • The language of the program is the programming language PL, the language in which the examination is done is the meta programming language MPL. PL and MPL can be the same language.
  • There are different ways that Javascript allows us to inspect its own program.

1. To iterate over the members of an object

  • Example:
var person = {
    fname: "Default",
    lname: "Default",
    getFullName: function(){
        return this.fname + " " + this.lname;
    }
}

var john = {
    fname: "John",
    lname: "Doe"
}

john.__proto__ = person;

//Reflection : Iterate over the members of an object
for(var prop in john){
    console.log(prop + " : " + john[prop]);
}

OUTPUT : enter image description here

NOTE : When examining the properties of an object, JavaScript’s default is to include inherited properties.

  • In order to iterate over all the direct or own or non-inherited members of an object, we can use hasOwnProperty().
  • The hasOwnProperty() method returns a boolean indicating whether the object has the specified property as its own property (as opposed to inheriting it).
  • Syntax :
obj.hasOwnProperty(prop)
  • Example :
var person = {
    fname: "Default",
    lname: "Default",
    getFullName: function(){
        return this.fname + " " + this.lname;
    }
}

var john = {
    fname: "John",
    lname: "Doe"
}

john.__proto__ = person;

//Reflection : Iterate over the direct or own members of an object
for(var prop in john){
    if(john.hasOwnProperty(prop)){
           console.log(prop + " : " + john[prop]);
       }
}

OUTPUT : enter image description here

  • Object.getOwnPropertyNames() method returns an array of all properties (including non-enumerable properties except for those which use Symbol) found directly in a given object.
var person = {
    fname: "Default",
    lname: "Default",
    getFullName: function(){
        return this.fname + " " + this.lname;
    }
}

var john = {
    fname: "John",
    lname: "Doe"
}

john.__proto__ = person;

//Reflection : Iterate over the direct or own members of an object using Object.getOwnPropertyNames()
console.log(Object.getOwnPropertyNames(john));//["fname", "lname"]
  • Object.getOwnPropertyDescriptor() method returns a property descriptor for an own property (that is, one directly present on an object and not in the object's prototype chain) of a given object.
//Reflection : Getting the property descriptor for an own property of object
console.log(Object.getOwnPropertyDescriptor(person, 'getFullName'));//{writable: true, enumerable: true, configurable: true, value: ƒ}
  • Here:

    1. value : The value associated with the property (data descriptors only).
    2. writable : true if and only if the value associated with the property may be changed (data descriptors only).
    3. configurable : true if and only if the type of this property descriptor may be changed and if the property may be deleted from the corresponding object.
    4. enumerable : true if and only if this property shows up during enumeration of the properties on the corresponding object.
  • The static method Object.defineProperty() defines a new property directly on an object, or modifies an existing property on an object, and returns the object.

  • Syntax :
Object.defineProperty(obj, prop, descriptor)
  • By default, values added using Object.defineProperty() are immutable.

2. To examine all the properties of an object - If we want to distinguish between properties and methods of an object, we can use the operator typeofthat returns a string that identifies the type of the analyzed element.

//Reflection : To examine all the properties of an object
for(var prop in person){
    if(typeof person[prop] != 'function'){
        console.log(prop + " : " + john[prop]);
       }
}
//OUTPUT:
//fname : John
//lname : Doe

3. To examine all the methods of an object

//Reflection : To examine all methods of an object
for(var prop in person){
    if(typeof person[prop] == 'function'){
        console.log(prop + " : " + john[prop]);
       }
}
//OUTPUT:
//getFullName : function(){
//        return this.fname + " " + this.lname;
//    }

JavaScript already has reflection features in ES5 even though they were not named reflection either by specification or by the community. Methods such as Array.isArray , Object.getOwnPropertyDescriptor and Objects.keys acted much like the features reflection exhibits. The Reflect built-in in ES6 now houses methods in this category.

Related