
- Subscribe to RSS Feed
- Mark as New
- Mark as Read
- Bookmark
- Subscribe
- Printer Friendly Page
- Report Inappropriate Content
NOTE: MY POSTINGS REFLECT MY OWN VIEWS AND DO NOT NECESSARILY REPRESENT THE VIEWS OF MY EMPLOYER, ACCENTURE.
DIFFICULTY LEVEL: ADVANCED
Assumes having taken the class SSNF and has good intermediate to advanced level of knowledge and/or familiarity with Scripting in ServiceNow.
Building off of two of my recent articles (Extending GlideRecord, and Advanced Object Filter) I will show you how you can use MDN ECMAScript 6 Polyfill definitions to extend JavaScript in ServiceNow.
So, what does this mean exactly. Well with JavaScript it is possible to define future functionality using what are called Polyfills. A Polyfill implementation is simply a prototype that implements the new functionality. Now using the method I described in Extending GlideRecord you can also extend the base JavaScript language!
Here is how.
Note: When I originally published this article NONE of these were incorporated into the platform. Since October 2015, and without any fanfare, ServiceNow has snuck the majority of them into the Global platform codebase. I am tickled pink about that as anything that gets us closer to the current release of JavaScript (sic. NOT 2011) I am big-time for! MDN has removed most of these polyfills from their site, but you can still find them here: https://reference.codeproject.com/javascript/reference/global_objects/array
Lab 1.1: Finding and Using the ECMAScript 6 Polyfills
1. Here is the location of a few useful polyfills (test scripts are from the links - so don't judge!):
String.repeat (RETIRED - now part of platform) - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/repeat
Test script (works in global):
const mood = 'Happy! ';
gs.info('I feel {0}', [mood.repeat(3)]);
// Expected output: "I feel Happy! Happy! Happy!
String.startsWith (RETIRED - now part of platform) - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/startsWith
Test script (works in global):
const str1 = 'Saturday night plans';
gs.info(str1.startsWith('Sat'));
// Expected output: true
gs.info(str1.startsWith('Sat', 3));
// Expected output: false
String.includes (RETIRED - now part of platform) - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/includes
Test script (works in global):
const sentence = 'The quick brown fox jumps over the lazy dog.';
const word = 'fox';
gs.info('The word "{0}" {1} in the sentence', [word, sentence.includes(word) ? 'is' : 'is not']);
// Expected output: "The word "fox" is in the sentence"
String.endsWith (RETIRED - now part of platform) - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/endsWith
Test script (works in global):
const str12 = 'Cats are the best!';
gs.info(str12.endsWith('best!'));
// Expected output: true
gs.info(str12.endsWith('best', 17));
// Expected output: true
const str22 = 'Is this a question?';
gs.info(str22.endsWith('question'));
// Expected output: false
Array.fill (Still not part of the platform - very odd...did they miss one?) -
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/fill - explanation
https://reference.codeproject.com/javascript/Reference/Global_Objects/Array/fill - polyfill
a. Find the Polyfill in the referenced article (you will have to scroll down to see it).
b. Copy the entire Polyfill script out of the article and paste it into your new Script Include (described in the next step).
2. We can copy this code out pretty much without modification into a single Script Include.
a. Navigate to System Definition -> Script Includes.
b. Click on the New button to create a new Script Include
i. Name: JavaScriptExtensions
ii. Accessible from: All application Scopes
iii. Client callable: Un-checked.
iv. Description: Add ECMAScript6 functionality to the ServiceNow JavaScript library
v. Script: Replace the template with the code exactly as you find it (you can add others if you find them missing using the exact same method). With this script we are creating a language extension library of functions. Your code should look like this:
vi. Click the Submit button to save the new Script Include.
3. Once you save this you can "include" this Script Include in any client or server-side script of our choosing.
Lab 1.2: Testing the Polyfill functionality
1. Navigate to Scripts - Background.
2. Copy out the following script into the text box on Scripts-Background. Make sure that the "in scope" drop-down is set to Global. This script will be to test all of the functions that used be polyfills, but are now available with the platform!
a. Script:
const mood = 'Happy! ';
gs.info('I feel {0}', [mood.repeat(3)]);
// Expected output: "I feel Happy! Happy! Happy!
const str1 = 'Saturday night plans';
gs.info(str1.startsWith('Sat'));
// Expected output: true
gs.info(str1.startsWith('Sat', 3));
// Expected output: false
const sentence = 'The quick brown fox jumps over the lazy dog.';
const word = 'fox';
gs.info('The word "{0}" {1} in the sentence', [word, sentence.includes(word) ? 'is' : 'is not']);
// Expected output: "The word "fox" is in the sentence"
const str12 = 'Cats are the best!';
gs.info(str12.endsWith('best!'));
// Expected output: true
gs.info(str12.endsWith('best', 17));
// Expected output: true
const str22 = 'Is this a question?';
gs.info(str22.endsWith('question'));
// Expected output: false
b. Click the Run Script button to execute your script.
3. Your results will look like this:
*** Script: I feel Happy! Happy! Happy!
*** Script: true
*** Script: false
*** Script: The word "fox" is in the sentence
*** Script: true
*** Script: true
*** Script: false
4. Next let's test our new Polyfill script include.
5. Replace the code in Scripts - Background with the following:
gs.include('JavaScriptExtensions');
// Fill
const array1 = [1, 2, 3, 4];
gs.info(JSON.stringify(array1));
// Fill with 0 from position 2 until position 4
gs.info(JSON.stringify(array1.fill(0, 2, 4)));
// Expected output: Array [1, 2, 0, 0]
// Fill with 5 from position 1
gs.info(JSON.stringify(array1.fill(5, 1)));
// Expected output: Array [1, 5, 5, 5]
gs.info(JSON.stringify(array1.fill(6)));
// Expected output: Array [6, 6, 6, 6]
gs.info(JSON.stringify([1, 2, 3].fill(4))); // [4, 4, 4]
gs.info(JSON.stringify([1, 2, 3].fill(4, 1))); // [1, 4, 4]
gs.info(JSON.stringify([1, 2, 3].fill(4, 1, 2))); // [1, 4, 3]
gs.info(JSON.stringify([1, 2, 3].fill(4, 1, 1))); // [1, 2, 3]
gs.info(JSON.stringify([1, 2, 3].fill(4, 3, 3))); // [1, 2, 3]
gs.info(JSON.stringify([1, 2, 3].fill(4, -3, -2))); // [4, 2, 3]
gs.info(JSON.stringify([1, 2, 3].fill(4, NaN, NaN))); // [1, 2, 3]
gs.info(JSON.stringify([1, 2, 3].fill(4, 3, 5))); // [1, 2, 3]
gs.info(JSON.stringify(Array(3).fill(4))); // [4, 4, 4]
// A single object, referenced by each slot of the array:
const arr = Array(3).fill({}); // [{}, {}, {}]
arr[0].hi = "hi"; // [{ hi: "hi" }, { hi: "hi" }, { hi: "hi" }]
gs.info(JSON.stringify(arr));
const arr2 = new Array(3);
gs.info(JSON.stringify(arr2));
for (var i=0; i < arr2.length; i++) {
arr2[i] = new Array(4).fill(1);
}
gs.info(arr2[0][0]);
arr2[0][0] = 10;
gs.info(arr2[0][0]); // 10
gs.info(arr2[1][0]); // 1
gs.info(arr2[2][0]); // 1
const tempGirls = Array(5).fill("girl", 0);
gs.info(JSON.stringify(tempGirls));
const arrayLike = { length: 2 };
gs.info(JSON.stringify(Array.prototype.fill.call(arrayLike, 1)));
// { '0': 1, '1': 1, length: 2 }
The gs.include brings in and executes adding our Array.fill polyfill to the code base.
Click the Run Script button to execute your script.
Your results will look like this:
*** Script: I feel Happy! Happy! Happy!
*** Script: true
*** Script: false
*** Script: The word "fox" is in the sentence
*** Script: true
*** Script: true
*** Script: false
*** Script: [1,2,3,4]
*** Script: [1,2,0,0]
*** Script: [1,5,5,5]
*** Script: [6,6,6,6]
*** Script: [4,4,4]
*** Script: [1,4,4]
*** Script: [1,4,3]
*** Script: [1,2,3]
*** Script: [1,2,3]
*** Script: [4,2,3]
*** Script: [1,2,3]
*** Script: [1,2,3]
*** Script: [4,4,4]
*** Script: [{"hi":"hi"},{"hi":"hi"},{"hi":"hi"}]
*** Script: [null,null,null]
*** Script: 1
*** Script: 10
*** Script: 1
*** Script: 1
*** Script: ["girl","girl","girl","girl","girl"]
*** Script: {"length":2,"0":1,"1":1}
Try commenting out the gs.include and see what happens.
Also, the following code is an example of the Array.fill polyfill for ECMA6+. It is already part of the Scoped application platform, but this particular code does not work in Global. Since it already exists you do not need to add it to the platform. I am just presenting it as an example. I got this excellent example from here.
// ECMA 6+ version
// polyfill from:
if (!Array.prototype.fill) {
Array.prototype.fill = function(value, start, end) {
if (this == null) {
throw new TypeError('this is null or not defined');
}
const arr = Object(this);
const len = arr.length >>> 0;
const relativeStart = start >> 0;
const relativeEnd = end === undefined ? len : end >> 0;
const finalStart = relativeStart < 0 ? Math.max(len + relativeStart, 0) : Math.min(relativeStart, len);
const finalEnd = relativeEnd < 0 ? Math.max(len + relativeEnd, 0) : Math.min(relativeEnd, len);
for (let i = finalStart; i < finalEnd; i++) {
arr[i] = value;
}
return arr;
};
}
And that is it. Be careful in adding a polyfill to the platform without letting your customer or user owners know. It shouldn't bust anything, but you never know! Test, test, test, right?! Just saying.
Enjoy!
Steven Bell.
If you find this article helps you, don't forget to log in and mark it as "Helpful"!
Originally published on: 10-13-2015 08:02 AM
I updated the code and brought the article into alignment with my new formatting standard.
- 3,471 Views
You must be a registered user to add a comment. If you've already registered, sign in. Otherwise, register and sign in.