Master JavaScript Development in Adobe Campaign
Adobe Campaign Classic utilizes JavaScript as the backend language for customizing various aspects of your instance, including workflows, libraries, web applications, and reports. The platform employs the Java Web Server called Tomcat for its operation. To execute JavaScript on the server, Adobe Campaign Classic utilizes a JavaScript engine called SpiderMonkey.
SpiderMonkey, developed by the Mozilla Foundation, is responsible for executing JavaScript code on the platform. Currently, Adobe Campaign Classic uses SpiderMonkey 1.8.5, which was released in 2012. This version was significant at the time as it implemented the ECMAScript 5 (ES5) specification. ES5 introduced several new features and improvements to the JavaScript language. Adobe Campaign also extensively utilizes E4X (ECMAScript for XML) and the last version of SpiderMonkey that supported E4X was 1.8.0. E4X has been gradually deprecated in newer versions of SpiderMonkey and is no longer widely supported in modern JavaScript environments.
What we have in ECMAScript 5
The new features in ECMA ES5 were following
"use strict"
: directive in JavaScript that enables strict mode within a specific scope or an entire script. When “use strict” is used at the beginning of a script or a function, it instructs the JavaScript interpreter to enforce a stricter set of rules and behaviors.Property Access on Strings
: you can access individual characters or substrings within a string using property access notation. This allows you to retrieve or manipulate specific parts of a string based on their indices or positions.
To access a character at a specific index in a string, you can use square brackets ([]
) with the index value inside, starting from 0. For example
var str = 'hello'; str[0]; // h
Array.isArray()
: Checks if a value is an array.Array.prototype.forEach()
: Executes a provided function once for each array element.Array.prototype.map()
: Creates a new array with the results of calling a provided function on every element in the array.Array.prototype.filter()
: Creates a new array with all elements that pass the test implemented by the provided function.Array.prototype.reduce()
: Applies a function against an accumulator and each element in the array to reduce it to a single value.Array.prototype.reduceRight()
: Same as reduce(), but processes the array from right to left.Array.prototype.every()
: Tests whether all elements in the array pass the test implemented by the provided function.Array.prototype.some()
: Tests whether at least one element in the array passes the test implemented by the provided function.Array.prototype.indexOf()
: Returns the first index at which a given element can be found in the array.Array.prototype.lastIndexOf()
: Returns the last index at which a given element can be found in the array.Object.keys()
: Returns an array of a given object’s own enumerable property names.Object.defineProperty():
Adds or modifies a property on an object, optionally specifying attributes such as enumerable, writable, and configurable.Function.prototype.bind()
: Creates a new function that, when called, has its this keyword set to a provided value.JSON.parse()
: Parses a JSON string and returns the corresponding JavaScript value.JSON.stringify()
: Converts a JavaScript value to a JSON string.
What we do not have in ECMAScript 5?
Following is list of new features introduced to the next major release ECMAScript ES6 released in 2015
let
andconst
Declarations: Introduced block-scoped variables withlet
and block-scoped constants withconst
.- Arrow Functions: Introduced a concise syntax for writing function expressions.
let hello = (scriptVersion) => `You will be missed in ${scriptVersion}`;
Template Literals
: Introduced a new way to create strings using backticks (`Hi there ${}`) with embedded expressions.Default Parameters
: Allowed function parameters to have default values.Rest Parameters
: Enabled the use of the rest parameter syntax (...
) to represent an indefinite number of arguments as an array.Spread Syntax
: Allowed an iterable (e.g., an array) to be expanded in places where multiple arguments or elements are expected.Destructuring Assignment
: Provided a concise way to extract values from arrays or objects into distinct variables.Classes
: Introduced a new syntax for defining classes, including support for constructor methods and inheritance.Modules
: Introduced a standardized module format to organize and share JavaScript code between files.Promises
: Introduced a built-in mechanism for handling asynchronous operations, simplifying callback-based async code.Array.from()
: Created a new array from an array-like or iterable object.Array.find()
and Array.findIndex(): Introduced methods for finding elements in an array based on a provided callback.Object.assign()
: Allowed properties from one or more source objects to be copied to a target object.Enhanced Object Literals
: Provided shorthand notations for defining object properties and methods.Symbol
: Introduced a new primitive type to create unique identifiers, useful for defining object properties.Map and Set
: Introduced new built-in data structures for collections with unique keys (Map) and unique values (Set).Iterators and Iterables
: Introduced a protocol for iterating over data structures using thefor...of
loop and theSymbol.iterator
method.
Among the new features, the one I will miss the most are:
-
Arrow functions
: as they significantly reduce the amount of code I need to type. And they look amazing and everybody get feeling like you know what you are doing, just look at them.
//arrow functions let m = (a, b) => a*b //classic functions var m = function (a, b){ return a*b; }
Template Literals
: Every line has to be either concatenated with ‘+’ or using multiline feature of ES 5.
//template literals const str = `Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aliquam imperdiet, massa at tempus scelerisque, urna sem hendrerit magna, a luctus odio urna vel nunc. Donec a volutpat magna. In iaculis lacus euismod magna fringilla tincidunt ut sed quam. Sed ac nisl non lacus dignissim vehicula vitae id purus.`; const str2 = `Hello there ${name}`; //old way //do mind that this will not work with ' also adobe campaign does not recognize this syntax even though //it is valid and will run without error var str = "Lorem ipsum dolor sit amet, consectetur adipiscing elit.\ Aliquam imperdiet, massa at tempus scelerisque, urna sem hendrerit magna, a luctus odio urna vel nunc.\ Donec a volutpat magna. In iaculis lacus euismod magna fringilla tincidunt ut sed quam.\ Sed ac nisl non lacus dignissim vehicula vitae id purus."; var str2 = 'Hello there ' + name;
Rest Parameters
: Rest parameters are a feature introduced in ECMAScript 6 (ES6) that allow a function to accept an indefinite number of arguments as an array. It’s denoted by the ellipsis (...
) followed by a parameter name. Here’s an example:
function sum(...numbers) { let total = 0; for (let number of numbers) { total += number; } return total; } console.log(sum(1, 2, 3, 4)); // Output: 10
In ECMAScript 5 you need to handle dynamic arguments manually. For that we use the arguments
built-in object that provides access to the arguments passed into a function. It allows you to access the arguments dynamically, regardless of the number of parameters defined in the function’s declaration.
loadLibrary('xtk:shared/nl.js'); var sum = function () { var sum = 0; if (arguments.length === 0) logError('No arguments provided!!') for (var i = 0; i < arguments.length; i++) { if (!NL.isEmpty(arguments[i]) && NL.isNumber(parseInt(arguments[i]))) sum+=parseInt(arguments[i]); } return sum; } logInfo(sum(1,2,3,4));//06/01/2023 9:20:52 AM js3 10
Spread Syntax
: Spreading is the opposite of rest parameters. It allows an array to be expanded into individual elements. The spread syntax is also denoted by the ellipsis (...
). Here’s an example:
const numbers = [1, 2, 3, 4]; console.log(...numbers); // Output: 1 2 3 4 const array1 = [5, 6]; const array2 = [7, 8]; const mergedArray = [...array1, ...array2]; console.log(mergedArray); // Output: [5, 6, 7, 8]
Destructuring Assignment
: Destructuring allows us to extract values from arrays or objects into distinct variables. Here are examples of array and object destructuring:
// Array destructuring const numbers = [1, 2, 3]; const [a, b, c] = numbers; console.log(a, b, c); // Output: 1 2 3 // Object destructuring const person = { name: 'Alice', age: 30 }; const { name, age } = person; console.log(name, age); // Output: Alice 30
Next major thing introduced with ES 6 are Promises
. Promise is an object that represents the eventual completion (or failure) of an asynchronous operation and its resulting value. Promises are commonly used when dealing with asynchronous operations such as fetching data from a server, making API requests, or handling time-consuming tasks.
The primary purpose of a Promise is to handle asynchronous code in a more organized and manageable way, avoiding excessive callback nesting (a phenomenon known as “callback hell”). Promises provide a clean syntax and a set of methods to handle the results of asynchronous operations.
Pollyfils
We may not have access to fancy features like spread syntax or destructuring in older ES versions, but what we can do is implement the functions we miss from newer ES versions. To achieve this, we use polyfills, which can be easily found and utilized if needed.
Polyfills in JavaScript are code snippets or libraries that provide modern functionality to older JavaScript environments that do not natively support those features. They help bridge the gap between older JavaScript versions and the latest ECMAScript specifications, allowing developers to use newer language features in older environments.
To create a polyfill for the Array.find()
method in ES5, which was introduced in ES6 (ES2015), you can add the following code:
if (!Array.prototype.find) { Array.prototype.find = function(callback, thisArg) { if (this == null) { throw new TypeError('Array.prototype.find called on null or undefined'); } if (typeof callback !== 'function') { throw new TypeError('callback must be a function'); } var list = Object(this); var length = list.length >>> 0; var thisArg = arguments[1]; for (var i = 0; i < length; i++) { var element = list[i]; if (callback.call(thisArg, element, i, list)) { return element; } } return undefined; }; }
The above code checks if the Array.prototype.find
method already exists. If it doesn’t, it creates the find
method and assigns it a custom implementation. The polyfill replicates the behavior of Array.find()
by iterating through the array and invoking the provided callback function on each element until a match is found.
Note that this polyfill checks for the existence of Array.prototype.find
before creating it to prevent overriding native implementations if they already exist in the JavaScript environment.
Sujith
says:Great one. Can you please upload about rest and soap api too. That will be useful.