This blog aims to explain JavaScript’s prototype with respect to ServiceNow. Prototype is a fundamental concept in JavaScript. In order to understand ‘Prototype’, one should know about objects and property (variable defined on a function) in JavaScript.
There are two concepts with prototype which is interrelated:
1. Every JavaScript function contains ‘prototype property’ which is empty by default. If one wants to implement inheritance in ServiceNow then properties and methods can be attached on this ‘Prototype Property’ to make those methods and properties available to particular instances of that function.
Please find below as a sample example of inheritance with ‘prototype’ property:
function Demo(getData) {
this.documents = getData;
}
//As long as one adds the fetch() method to Demo prototype property, than other objects can inherit it. Demo.prototype.fetch = function () {
console.log(this.documents);
};
// create a new object with the Demo constructor, since it’s allowing this new object to inherit
//Demo’s properties and methods.
var newObject = new Demo (“This is new Object and it can fetch the data.”);
// newObject inherited all the properties and methods, including the fetch method, from the Demo //function.
// Now newObject can call fetch directly, even though one never created a fetch() method on it.
newObject.fetch (); // This is new Object and it can fetch the data.
In ServiceNow, the GlideAjax class allows a client-side script to make an AJAX call to the server, execute
server-side script include and even return a value. It has both a client-side and a server-side component.
At Server side: A GlideAjax call from a client-side script will ultimately execute a script include
(which is a server-side script). For example, a script include (GetPropertyAjax) is created that will return the value of a system property. Once anyone enters this name, the default scaffolding of the script include is populated into the Script field.
To make this script include accessible from client-side scripts via GlideAjax, one need to check the Client callable check-box. This will alter the contents of the Script field so that script include extends the ‘AbstractAjaxProcessor’ class. It also removes the initialization method, since one will not be initializing this class from the server.
Next, one needs to define a method of GlideAjax script include that will retrieve the value of the system property and return it to the client.
In the ‘getProp’ method, note that one is calling this.getParameter() in the preceding code.
This is a method specific to the AbstractAjaxProcessor class, which is extending. It means that all methods of the AbstractAjaxProcessor class are now also member methods of the GetPropertyAjax class which was created. While accessing methods of this inside class, one is able to access those methods as well. This method in particular, retrieves the value of the sysparm that will be sent while calling this GlideAjax script from client-side script.
Client-Side script: To create a client-side script, one needs to declare an instance of the GlideAjax class, passing the GlideAjax script include name into the clientside constructor. Afterwards, use the addParam() method to specify two parameters: sysparm_name and sysparm_prop_name:
The sysparm_name parameter is mandatory. It tells the GlideAjax script which method, one wants to run.
The sysparm_prop_name parameter is custom-defined. It’s just a name that one agreed to expect on the server-side script include and provide from the client-side script.
When a GlideAjax script returns a value, it doesn’t return it like a normal function. Instead, after specifying all of the necessary parameters, one can call another method of the GlideAjax class in client-side script: getXMLAnswer() or getXMLWait().
This method accepts one argument: a callback function, as shown in the following snippet:
2.The second type is ‘prototype attribute’ which identify the characteristic of the object and it tells the object’s parent. In other words, the ‘prototype attribute’ of object points to its ‘Parent’. While creating a ‘new object’, the prototype attribute is referred as a prototype object which sets automatically.
Constructor in JavaScript and ServiceNow:
In JavaScript, the constructor is a function which is used for initializing ‘new objects’ and use new keyword to call constructor.
For example:
function Registration () {
}
// this is the use of the Registration constructor to create the userRegister object.
var userRegister = new Registration ();
Moreover, all objects that inherit from another object, inherit constructor property as well. The constructor property is simply a property (like any variable) which holds or points to the constructor of that object.
//The constructor in this example is Object ()
var myObject = new Object ();
// And if one later want to find the myObject constructor:
console.log(myObject.constructor); // Object()
// Another example: Registration () is the constructor
var userRegister = new Registration ();
// Find the userRegister object’s constructor
console.log(userRegister.constructor); // Registration ()
In ServiceNow, this constructor function is usually called ‘initialize’ method. Any arguments passed into the class during instantiation will be passed into this function, which effectively builds the object that will be returned.
Here is an example of what a very simple class might look like:
On line 1: Declare class (MyClass) using a special ServiceNow API, Class.create().
it happens, JavaScript doesn’t technically have a data type called Class. Instead, it relies on function/object prototype extensions. In order to simplify this and provide syntax more similar to the backend Java (and more similar to what most object oriented programming languages use), ServiceNow provides Class.create() as a simple way to generate a basic class-esque object.
On line 2: Take this basic class scaffolding that was generated on line one and extend that
Prototype by adding some stuff to it (everything between the curly braces: { and }).
On line 3: Declare the initialize method. This is a special method of class, which is called automatically whenever a new object is instantiated from our class using the new keyword like:
var myObj = new MyClass(‘input’);
Any arguments passed into this instantiation process (the string input in the preceding case) are passed into this initialization method.
On line 4: Set a property in the scope of the instantiated object using the keyword. In this case, at the creation of an instance of this class, the property called localProperty will be initialized with the value that was passed into the constructor function.
On line 6: Declare another method called getLocalProperty. This is a method that can be called from objects created from our class.
On line 7: Returns the value of the property that was set on initialization.
On line 9: Declare the type property of your class (and instantiated objects). This is just a string that can be accessed to determine the origin of class child objects.
Why is Prototype Important and when is it used:
As mentioned above, there are two ways the prototype can be used in JavaScript.
- Prototype Property: Prototype-based Inheritance:
The ‘PROTOTYPE’ is important because JavaScript does not support classical inheritance which is based on classes therefore ‘prototype property’ makes possible all the inheritance in JavaScript.
JavaScript has a prototype-based inheritance mechanism and it’s implemented with ‘prototype property’.
For example:
After creating a Car function, adding properties and methods on the Car prototype property, all instances of the Car function will inherit all the Car’s properties and methods.
Illustration of Inheritance in JavaScript:
function Vehicle () {
this.city= “Pune”;
this.isElectric = true;
}
// Add the showTypeAndBrand method to the Vehicle prototype property
Vehicle.prototype. showTypeAndBrand = function () {
console.log(“It is ” + this.type+ ” and brand is ” + this.color);
};
// Add the isItElectric method to the Vehicle prototype property
Vehicle.prototype. isItElectric = function () {
if (this. isElectric)
console.log(“It is an Electric car!”);
};
function Car (carType, carBrand) {
this.type = carType;
this.brand= carBrand;
}
// Set the Car’s prototype to Vehicle’s constructor, thus inheriting all of Vehicle.prototype methods and properties.
Car.prototype = new Vehicle ();
// creates a new object, sportsCar, with the Car constructor
var sportsCar = new Car (“Veyron”, “Bugatti”);
// Here sportsCar uses the ‘type’ property from the sportsCar object prototype, which is Car.prototype:
console.log(sportsCar.type); // Veyron
// Uses the showTypeAndBrand method from the Car object prototype, which is Vehicle.prototype.
// The sportsCar object inherits all the properties and methods from both the Vehicle and Car functions.
console.log(sportsCar. showTypeAndBrand ()); // It is Veyron and brand is Bugatti.
The sportsCar object inherited ‘showTypeAndBrand method’ even though it had already defined all the way up the prototype chain on the Vehicle.prototype object.
Any object that uses the Car () constructor will inherit all the Car.prototype properties and methods. Also, it will inherit all the properties and methods from the Car’s prototype, which is Vehicle.prototype.
This is the proper way in which inheritance is implemented in JavaScript and the integral role the prototype chain has in the process.
Prototype Attribute: Accessing Properties on Objects:
Prototype is also important in order to access properties and methods of any object. The prototype attribute (or prototype object) of any object is the ‘parent’ object where the inherited properties were originally defined.
It is loosely comparable to the way one might inherit their surname from their father—he is their
‘prototype parent’. If one wants to find out where their surname came from, first check to see if it was created himself, if not, then search will move to their prototype parent to see if they inherited it from father. If it was not created by father as well then the search continues to his father (their father’s prototype parent).
Similarly, if one wants to access a property of an object, the search for the property begins directly on the object. If JavaScript runtime do not get the property at that place then it looks the property on the object’s prototype – the object from which it inherited its property from.
Assume, property is not found on the object’s prototype then the search continues the search to prototype of object’s prototype and it goes up until no more prototypes left. If the property is not available on the object’s prototype, the search for the property then moves to prototype of the object’s prototype (the parent of the object’s parent—the grandparent). And this continues until there is no more prototype (no more great-grand father, no more lineage to follow).
In other words, it is called prototype chain: the chain from an object’s prototype to its prototype’s then its prototype and so on. And JavaScript uses this prototype chain to look for properties and methods of an object.
If any property is not available on any of its object’s prototype, then in the prototype chain, the property does not exist and ‘undefined’ is returned.
As mentioned above, the prototype chain mechanism is same as the prototype-based inheritance, except on JavaScript. How does it access the object properties and methods via the prototype object?
Following example illustrates the prototype chain of object’s prototype object:
var myFriends = {name: “Alias”};
// In order to find the ‘name’ property, the search will start on the myFriends object and find name //property
// It would be part of prototype chain with one link.
console.log(myFriends.name);
// As mention below, the search to find the toString () method would also start on the myFriends’ object,
// but one never created a toString method on the myFriends object then the compiler will search for it on the myFriends prototype (object which is inherited its properties from).
// since all objects created with the object literal inherits from Object.prototype, the toString method
// will be found on Object.prototype—see important note below for all properties inherited from
// Object.prototype.
myFriends.toString ();
Object.prototype Properties Inherited by all Objects. All objects in JavaScript inherit properties and methods from Object.prototype.
These inherited properties and methods are constructor, hasOwnProperty (), isPrototypeOf (),
propertyIsEnumerable (), toLocaleString (), toString (), and valueOf ().
ECMAScript 5 also adds 4 accessor methods to Object.prototype.
Please look into one more example of the prototype chain:
function InformationTechnology () {
this.leadOrg = “Microsoft”;
}
// define “level5” property on the InformationTechnology prototype so that “level5” is accessible by all objects that //use the InformationTechnology () constructor.
InformationTechnology.prototype.level5 = “IBM”;
var topOrg= new InformationTechnology ();
topOrg.leadOrg = “Google”;
// The search for leadOrg will first look for the leadOrg property on the topOrg object, and since one //defined it there, that is the property that will be used. Because one have overwritten the topOrg’s //leadOrg property with one directly on the topOrg object, the search will NOT proceed up the prototype chain.
console.log (topOrg.leadOrg); // Google
// Note: In ECMAScript 5 one can set a property to read only, and in that case one cannot overwrite it as //one just did.
// This will show the property from the topOrg prototype (InformationTechnology.prototype), since the // level5 property was not defined on the topOrg object itself.
console.log (topOrg.level5); // IBM
// In this example, the search proceeds up the prototype chain and find the toString method on
// Object.prototype, from which the topOrg object inherited—all objects ultimately inherits from
// Object.prototype as we have noted before.
console.log (topOrg.toString()); // [object Object]
Note: All built-in constructors (Array (), Number (), String (), etc.) were created from the Object constructor, and as such their prototype is Object.prototype.
Create a new ‘Prototype Attribute’:
There are two ways to create ‘Prototype Attribute’ of any object by using “new Object()” or “Object Literal”. All the objects are created with object literals and with the Object constructor (new Object()) which inherits from Object.prototype.
Hence, ‘Object.prototype’ is the prototype attribute (or the prototype object) of all objects created with
new Object () or with {}. ‘Object.prototype’ itself does not inherit any methods or properties from any other object.
// The userAccount object inherits from Object and as such its prototype attribute is Object.prototype.
var userAccount = new Object ();
// this shows the use of “object literal” to create the userAccount object; the userAccount object inherits from Object; therefore, its prototype attribute is Object.prototype just as the userAccount object does above.
var userAccount = {name: “Mike”}
Note: In ECMAScript 5, one can create objects with an Object.create() method that allows to set the new object’s prototype object.
Conclusion:
In ServiceNow, Mozilla Rhino is an open-source implementation of JavaScript, written entirely in Java.
Despite the similar-sounding names, Java and JavaScript are vastly different languages. It is important for ServiceNow administrators and developers to know the difference.
One does need to know JavaScript as it helps to understand the class-based nature of languages like Java. This is because in server-side scripts, some class-based functionality is available in ServiceNow specifically in the form of Script Includes. In fact, the default scaffolding of a new Script Include defines it as a class with the same name as the Script Includes itself.
JavaScript, the language used to both define and access the code in Script Includes, is an Object Oriented language, but it is not a class-based one.
Instead, JavaScript is a prototypal object-oriented language. One can declare a class in JavaScript which is actually a function, and then extend the prototype of that function by adding ‘member’ functions (otherwise known as methods) or member variables (otherwise known as properties).
Typically, JavaScript classes are defined and extended using the following syntax:
On lines 1-3: One declares the class itself. It looks like a function, that’s because it is In JavaScript. Functions are just objects and objects with extended prototypes are classes. This first function is effectively the Constructor of the ‘MyClass’ class.
On lines 4-10: One extend the class prototype by declaring a new member method, displayMessage(). Though the ‘msg’ variable is not declared in the context of this method, one is able to access it as a property of the object in which it was initialized, using the ‘this’ keyword.
Now that the ‘MyClass’ class is defined, one can declare an object instance of it by calling the constructor method using the new keyword and access methods of the object like:
var mc = new MyClass(‘This is a test string.’);
mc.displayMessage();
This would result in a message being logged to the console: This is a test string.
This prototypal object extension is accessible in server-side scripts as well but ServiceNow also exposes some Java-esque class description functionality, using Class.create() in Script Include.
We hope this blog has helped you in understanding Service Now working with Java Script protoype in an efficient way.