JavaScript Topics

Introduction Template Literals Promises Closures Arrow Functions Rest Parameters Combine Arrow, Rest, Array Reduce Strict Mode Simple Module Simple Import Module, Import, Event Listener Summary

Introduction

Learn some advanced JavaScript techniques including template literals, template literals with expressions, promises, closures, arrow functions, rest parameters, strict mode, imports and modules. We'll also combine rest parameters with arrow functions.

Template Literals

Template Literal Substitution

A template literal with substitution allows developers to substitute variable values within brackets. A template bracket begins with ${ and ends with }.

Insert strings sBreed and sType into the string text, within brackets ${..}. The return value equals Animal: Savannah, Cat.. Click the box to see the result, below. The following function, fTemplate() includes the code to return a string from a template literal.

function fTemplate(){
let sBreed = "Savannah";
let sType = "Cat";
let text = `Animal: ${sBreed}, ${sType}.`;
return text;
}

Template Literal Expression

A template literal with an expression allows an expression within a template. The template begins with ${ and ends with }.

The expression (start * growth).toFixed(2) evaluates between the brackets ${...}. The result should display Final: 27.50. Click a box to see the result, below. The following function includes the code to return a string from a template literal with an expression.

function fTempExp(){
let start = 22;
let growth = 1.25;

let final = `Final: ${(start * growth).toFixed(2)}`;
return final;
}

Click a Box

Template Literal Substitution
function fTemplate(){
let sBreed = "Savannah";
let sType = "Cat";
let text = `Animal: ${sBreed}, ${sType}.`;
return text;
}
Template Literal Expression
function fTempExp(){
let start = 22;
let growth = 1.25;
let final = `Final: ${(start * growth).toFixed(2)}`;
return final;
}

Closures

Declare a closure as a child function within a parent function. The child function retains access to properties in the parent scope.

Simple Factorial

Call factorial() the number of times you want to calculate a factorial, starting at one. The factorial from one to four should equal 1 * 2 * 3 * 4 = 24. The following code displays a simple method to process the factorial of four. The last statement, this.innerHTML = factorial(); is the fourth call to factorial() and displays the result in an HTML element.

factorial(); factorial(); factorial(); this.innerHTML = factorial();
Simple Factorial Closure

Tap a box below to see closure examples in action. The simple factorial closure source code displays below.

/**
 * Factorial equals the
 * product of a series of numbers.
 * 1 * 2 * 3 * 4...
 */
const factorial = (function () 
{
 let f = 1;
 let r = 1;
 
 // The closure:
 return function () 
 { 
  console.log("f: "+f+ ", r:"+r);
  console.log("f * r: " +f * r);
  r = f * r;
  f += 1; 
  return r;
 }
}
)();
Factorial with End Value Parameter

A slightly simpler closure includes a parameter which indicates the factorial end point. For example if you want to see the factorial of seven, call factorialN(7);.

Pass a parameter to the factorial function. The parameter indicates the last number in a series of products. For example if you call factorialN(4), the result should equal 1 * 2 * 3 * 4 = 24.

Tap a box below to see both closure examples in action. The code below demonstrates one technique to use a closure to process factorials. However closures have many more uses.

/**
 * Factorial equals the
 * product of a series of numbers.
 * 1 * 2 * 3 * 4
 * @param n: Number representing 
 * end of factorial calculation.
 */
const factorialN = (function (n) 
{
 let f = 1;
 let r = 1;
 return function (n) 
 { 
  for (var i = 0; i < n; i++){
   console.log("f: "+f+ ", r:"+r);
   console.log("f * r: " +f * r);
   r = f * r;
   f += 1; 
  }
  return r;
 }
}
Tap the Box
Call factorial from one to four. Should equal 24.
Enter Factorial Digit Below:
0

Promises

Promises link long running code with result handler functions, which wait for a response.

Producer
Code that takes time.
Consumer
Code that waits for result.
Promise
Link between Consumer and Producer

Order

First define your promise handler or handlers. Second create a Promise object. Third call the promise.

  1. Define Promise Handler; displayInfo().
  2. Create Promise object; var promiseButton = new Promise(...)
  3. Call Promise; promiseButton.then(...)

Promise Handler

Define a promise handler that simply displays the result. This handler can be used if the Promise results in an error, or acceptable responses.

function displayInfo(sInfo){
let eDebug = document.getElementById('eDebug');
eDebug.innerHTML = sInfo;
}

Create a Promise

The following code creates a Promise with status handlers for either an error or acceptable responses.

This promise handler calls an XMLHttpRequest() to download an XML file.

var promiseButton = new Promise(

function(resolveOK, resolveError) {

let req = new XMLHttpRequest();

req.open('GET', 
"assets/ss-promise-got.html"
);

req.onload = function() {

if (req.status == 200) {

// Download went well.
resolveOK(req.response);

}

else {

// Download error:
rejectError("File not Found");

}

};


// Execute the download:
req.send();

});

Call a Promise

Call the promise, with the resolveOK() and resolveError() functions in order. The following function, promiseCall() responds when the user taps a button.

function promiseCall(){
promiseButton.then(
function(value) {displayInfo(value);},
function(error) {displayInfo(error);}
)
}

The following HTML markup executes promiseCall() when the user taps the div element.

<div 
id="eDebug"
onclick="promiseCall()"
>
</div>

Tap for Promise

The button below calls a function which activates promiseButton.then(...). I created the promiseButton, outside of the calling function, with a var instead of let. That allowed me to define the promise earlier, and allows the function to access the promise.

Requires CORS

Either enable CORS or copy files to a Web server. Otherwise the promise won't download the file, assets/ss-promise-got.html.

Tap the Button!

Arrow Functions

Arrow functions have a unique signature, and different parent element, than normal JavaScript functions. Signature pseudo code, for an arrow function, follows.

functionName = (parameters) => function body;

You can remove brackets and the return keyword for functions with only one statement and a return value.

The following two function definitions demonstrate how to accomplish the same task with either a normal function or an arrow function.

// Before
fHi = function() {
return "Hi Web Developer!";
}

// Arrow
fHi = () => "Hi Web Developer!";

The following two examples demonstrate arrow functions with parameters.

// Before
function fMultiply(a,b){ 
return a * b;
}

// Arrow
let fMultiply = (a, b) => a * b;

Normally the this property is the object that calls a function, such as a button. With arrow functions this property is the function's owner, in this case the owner is the window.

// Normal
fNormal = function() {
btnNormalTxt = document.getElementById("btnNormalTxt");
btnNormalTxt.innerHTML = this;
}

document.getElementById("btnNormal").addEventListener(
"click", 
fNormal
); 

// Arrow
fArrow = () => {
btnArrowTxt = document.getElementById("btnArrowTxt");
btnArrowTxt.innerHTML = this;
}

document.getElementById("btnArrow").addEventListener(
"click", 
fArrow
); 

Tap Both Buttons

The small text, toward the bottom of each button, tells you which type of object this represents.

Rest Parameters

Rest parameters allow JavaScript variadic functions. When the function's defined, include a rest parameter, preceded by three dots, such as f(...restParam);. You may treat the rest parameter as an array.

A variadic function includes a variable number of parameters. Developers can modify the number of parameters when the function's called.

Rest parameters are also called spread operators.

Rest Example

For example, the following function, fRest(), displays the first two parameters, p1 and p2, with the last parameter, aryMore. Tap the red box to see the results. Notice the parameter, ...aryMore, displays as an array. See the HTML Simple Rest Markup.

function fRest(p1, p2, ...aryMore) {

let eRest = document.getElementById('idRest');

eRest.innerHTML = "p1: "+p1+"<br>p2:"+p2+"<br>aryMore:"+aryMore+",";

}

Simple Rest Markup

Function fRest() displays the first two parameters, Greyhound, Poodle as unique values. The last three parameters, Boxer, Chihauhau, Shepherd, display as the contents of an array.

<div 
class="box"
id="idRest"
style="background-color:red;"
onclick="fRest(
'Greyhound',
'Poodle',
'Boxer',
'Chihuahua',
'Shepherd'
)";
>

Tap to call fRest()

</div>

Rest Buttons

Tap to call fRest()
Tap to call fReduce()

Combine Arrow, Rest Parameter, Array Reduce

This section applies the Array reduce() method, with an arrow function on a rest parameter.

Function: Arrow with Reduce Array

The reduce() array method iterates over an array. Method reduce() applies the result of each previous call to the current call of a developer defined function. The end result is one value.

The first parameter to reduce() is a developer defined function. The second, optional, parameter is the starting value for the developer defined function.

The following code defines a function for reduce() that multiplies the sequence of values in an array. Tap the green box to see the results of the fReduce() function, below.

// Arrow function
// Multiplies a series
// of numbers in an array.
const fReduceMultiply = (prev, curr) => prev * curr;

function fReduce(){
// Obtain the button.
let eReduce = document.getElementById('idReduce');

// Declare an array.
let aryOneToFour = [1, 2, 3, 4];

// 1 * 2 * 3 * 4 = 24.
eReduce.innerHTML = aryOneToFour.reduce(fReduceMultiply));
eReduce.innerHTML += "<br >";

// 5 * 1 * 2 * 3 * 4 = 120.
// Call fReduce with an initial value of five.
eReduce.innerHTML += aryOneToFour.reduce(fReduceMultiply, 5));

}

Order With Rest Array

Only one rest parameter is allowed per function and that rest parameter must be the last or only parameter. As you saw earlier, functions accept individual parameters passed before the rest array.

Order with Reduce Method

With array's reduce() method, the first parameter is an array, however the last parameter can provide the initial value to apply for reduce.

Rest Versus Reduce

Functions with Rest parameters require the Rest (array) parameter last and optional other parameters first. The array reduce() method requires the array parameter first and optional initial value last.

After some testing it appears that developers might not be able to pass non Rest parameters to the reduce() method. However perhaps that depends on the current browser's JavaScript version..

Product Arrow Function: Rest Parameter

Now create a function with a rest parameter then apply the reduce function defined previously, named fReduceMultiply().

The following simple function iterates over every value in rest parameter (array), ...aryArgs, multiplying each value by the preceding value. The product is returned.

/**
* Multiply every value in ...aryArgs.
* @param Rest or spread parameter: ...aryArgs
* @returns: product of array values.
*/
function fMult(...aryArgs) {
return aryArgs.reduce(fReduceMultiply);
}

Markup: Rest, Multiply, Arrow

<div 
class="box"
style="background-color:yellow; color:black;"
onclick="this.innerHTML = fMult(1,2,3,4)"
>
Tap to Multiply:<br>
(1,2,3,4)
</div>

Sum Arrow Function: Rest Parameter

Implement a function with a rest parameter. Define and call an arrow function to sum every value in the rest parameter's array. Return the sum.

/**
* Sum every value in ...aryArgs.
* @param Rest or spread parameter: ...aryArgs
* @returns: sum of array values.
*/
function fSum(...aryArgs) {
 return aryArgs.reduce((previous, current) => {
   return previous + current;
 });
}

Markup: Rest, Sum, Arrow

The following markup declares a box. Click on the box to see the sum of the rest parameter, 1,3,4,5. Try It: Rest, Arrow: Sum & Product.

<div 
class="box"
style="background-color:violet"
onclick="this.innerHTML = fSum(1,2,3,4)"
>
Tap to Sum:<br>
(1,2,3,4)
</div>

Try It: Rest, Arrow: Sum & Product

Tap to Multiply:
(1,2,3,4)
Tap to Sum:
(1,2,3,4)

Strict Mode

Strict mode was enabled in ECMAScript 5. Most browsers now support strict mode, yet older browsers ignore the simple string declaration. Strict mode throws an exception when the developer violates good practices, such as attempting to write to an undeclared variable, undeclared object, undeclared property or getter only property. Strict mode throws exceptions with many other violations of good practice, or use of reserved keywords, in preparation for future JavaScript versions. See the following lists for examples.

Strict Mode Errors

The following list includes examples which will throw an exception in strict mode.

Assign to Non Declared Variable
notStrict = "Throws an Error.";
Assign to Non Declared Object
myObject = {x:256,y:512}
Deleting a Variable
var firstName = "Doris"; delete firstName;
Deleting a function
function f(){ var x = 20;} delete f;
Duplicate Parameters
function f(x,x){var y = 0;}
Octal Literals
Don't use var y = 0256; Use character o after zero. Use var y = 0o256;.
Octal Escape Characters
Use hexadecimal escape sequences, \x45, not octal escape sequences, \105.
Write to Read Only Property
var obj = {};
Object.defineProperty(obj, 'name', { value: 'Doris', writable: false });
obj.name = 'Tony';
Write to Get Only Property
var obj ={get v(){return "v";}; obj.v = "a";

Reserved Keywords or Expressions

This list provides a clue as to which features W3C plans to implement in the future. For example perhaps access modifiers private, protected and public are on their way.

Don't use the following words as variables, functions or expressions, in strict mode.

this Property

In strict mode, the keyword this returns either the object that calls a function or undefined. In normal mode, the keyword this returns either the the object that calls a function or the window.

Apply Strict Mode

If you want JavaScript to run in strict mode then place the line, use strict;, at the top of a file. Strict mode then applies to the entire file. It's global. If you want a function only to run in strict mode, then place, use strict;, as the first line in a function.

function fStrictMode(){
"use strict";
// Throws an exception:
i = 0; 
}

Simple Module

Modules are simply files which enable sharing of functions, methods and properties. Use the keywords export and import to access features from one file to another file.

Create a file for modules, let's call it module-test.js. Apply the export keyword to specified functions, methods and properties. Those functions, methods and properties, will then be available outside of module-test.js.

For example create the following exportable function in module-test.js The function displays a string in the alert dialog.

/**
* Display an alert with a message.
* @param sMessage: String
*/
export function popupMessage(sMessage) {
alert('Popup Message: '+sMessage+'!');
}

Simple Import

Imports allow developers to load read-only modules of JavaScript, for use in their own files. Imports automatically load in strict mode.

Imports require CORS. Optionally copy pages and files to the same Web server.

Module Scope

Scripts loaded as a module are scoped to the script itself. That makes access within or without the script a challenge. I've seen suggestions to add the module to the window object. That doesn't seem like a good practice, but it might work best for your situation.

The following script imports everything exported from module-test.js to m. As soon as it load's, you'll see the alert with Hello World. You can view or download the JavaScript, module-test.js.

<script type="module">

import * as m from './javascript/module-test.js';

// Use exported values 
// from module-test here.

m.popupMessage('Hello World!');

</script>

Module, Import, Event Listener

This section demonstrates how to create a class module for export. Import the module and assign a module method as a click event listener, to a button.

I noticed many people online seemed to be looking for a simple solution to assign a straight forward JavaScript import, as an event listener. Here's one relatively simple example.

The following export module file, export-class.js, declares a class with two static functions. The first static function prints out to the console, for debugging purposes. The second static function changes the text on our button.

The last line declares that this class is for exporting, with export { expClass }. The entire JavaScript follows.

class expClass {
	
/**
* Log the function name,
* and parameter value.
	
* @param val: String
*/
static fLog = function(val) {

// The class and function:
console.log('expClass.fLog()');

// Name of parameter:
console.log('val'); 


// Value of parameter.
console.log(val); 

};


/**
* Change text on
* button when button tapped.
*/
static fBtnText = function() {

// Get the button's main text area:
let btnTxt = document.getElementById('btnTxt');

// Let user know, button clicked:
btnTxt.innerHTML = "Button Tapped!";

// Move to the button text:
window.location="#btnTxt";
};

};

export { expClass }

Module: Import Our Class

Import modules with the attribute type and value module. Obtain our button by Id, btnMod. Assign the expClass static method fBtnText to the button's onclick event listener.

View or download the JavaScript file, export-class.js. When you're done, tap the module button, and its text changes.

<script 
type="module"
>

// Import the class:
import {expClass} from './javascript/export-class.js';

// Call the logging function.
// Look in your console log:
expClass.fLog('Test log');

// Obtain our button.
btnMod = document.getElementById(
'btnMod'
);


if(btnMod != null){

// Add the on click listener:
btnMod.addEventListener(
'click',
expClass.fBtnText,
false
);

// Log that we have this button:
console.log(btnMod);

}
</script>

Tap the Button!

Button Markup

HTML markup for the button displays below.

<button 
class="btn" 
id="btnMod"
title="Test Module"
>

<span 
class="txt"
id="btnTxt"
>

Test Module

</span>

</button>

Summary

You learned some advanced JavaScript techniques including template literals, template literals with expressions, promises, closures, arrow functions, rest parameters, strict mode, imports and modules. We also covered how to combine rest parameters with arrow functions.

See the JavaScript advanced.js source file for this page. See the module JavaScript files, module-test.js and export-class.js.