Summary
A runtime environment is where your program will be executed. JavaScript code may be executed in one of two runtime environments:
- a browser’s runtime environment
- the Node runtime environment In each of these environments, different data values and functions are available, and these differences help distinguish front-end applications from back-end applications.
- Front-end JavaScript applications are executed in a browser’s runtime environment and have access to the window object.
- Back-end JavaScript applications are executed in the Node runtime environment and have access to the file system, databases, and networks attached to the server.
Modules
Note: The words “module” and “file” are often used interchangably
Instead of having the entire program written within my_app.js, its components are broken up into separate modules that each handle a particular task. For example, the database_logic.js module may contain code for storing and retrieving data from a database. Meanwhile, the date_formatting.js module may contain functions designed to easily convert date values from one format to another (a common headache among programmers!).
$ node celsius-to-fahrenheit.js 100
100 degrees Celsius = 212 degrees Fahrenheit
/* celsius-to-fahrenheit.js */
function celsiusToFahrenheit(celsius) {
return celsius * (9/5) + 32;
}
const celsiusInput = process.argv[2]; // Get the 3rd input from the argument list
const fahrenheitValue = celsiusToFahrenheit(celsiusInput);
console.log(`${celsiusInput} degrees Celsius = ${fahrenheitValue} degrees Fahrenheit`);
module.exports
/* converters.js */
function celsiusToFahrenheit(celsius) {
return celsius * (9/5) + 32;
}
module.exports.celsiusToFahrenheit = celsiusToFahrenheit;
module.exports.fahrenheitToCelsius = function(fahrenheit) {
return (fahrenheit - 32) * (5/9);
};
require()
/* water-limits.js */
const converters = require('./converters.js');
const freezingPointC = 0;
const boilingPointC = 100;
const freezingPointF = converters.celsiusToFahrenheit(freezingPointC);
const boilingPointF = converters.celsiusToFahrenheit(boilingPointC);
console.log(`The freezing point of water in Fahrenheit is ${freezingPointF}`);
console.log(`The boiling point of water in Fahrenheit is ${boilingPointF}`);
In this case, ./ is a relative path indicating that converters.js is stored in the same folder as water-limits.js. When you use require(), the entire module.exports object is returned and stored in the variable converters. This means that both the .celsiusToFahrenheit() and .fahrenheitToCelsius() methods can be used in this program!
Destructuring
/* celsius-to-fahrenheit.js */
const { celsiusToFahrenheit } = require('./converters.js');
const celsiusInput = process.argv[2];
const fahrenheitValue = celsiusToFahrenheit(input);
console.log(`${celsiusInput} degrees Celsius = ${fahrenheitValue} degrees Fahrenheit`);
Examples
/* shape-area.js */
const PI = Math.PI;
// Define and export circleArea() and squareArea() below
function circleArea(radiusLength){
return PI * radiusLength * radiusLength;
}
module.exports.circleArea = circleArea;
module.exports.squareArea = function(sideLength){
return sideLength * sideLength;
};
/* app.js */
const radius = 5;
const sideLength = 10;
// Option 1: import the entire shape-area.js module here.
const areaFunctions = require('./shape-area.js');
// Option 2: import circleArea and squareArea with object destructuring
const { circleArea, squareArea } = require('./shape-area.js');
// use the imported .circleArea() and .squareArea() methods here
// With option 1:
const areaOfCircle = areaFunctions.circleArea(radius);
const areaOfSquare = areaFunctions.squareArea(sideLength);
/*
Or with option 2:
const areaOfCircle = circleArea(radius);
const areaOfSquare = squareArea(sideLength);
*/
Resources
Introduction to JavaScript Runtime Environments
Example - Message Mixer
message-mixer.js
// Import the functions from encryptors.js here.
const encryptors = require('./encryptors.js');
const caesarCipher = encryptors.caesarCipher;
const symbolCipher = encryptors.symbolCipher;
const reverseCipher = encryptors.reverseCipher;
// User Input / Output Logic
/////////////////////////////////////////////
const encryptionMethod = getEncryptionMethod();
process.stdin.on('data', (userInput) => {
displayEncryptedMessage(encryptionMethod, userInput);
});
/* Helper function for determining which cipher method
the user chose when they ran the program. */
function getEncryptionMethod() {
let encryptionMethod;
const encryptionType = process.argv[2];
if (encryptionType === 'symbol') {
encryptionMethod = symbolCipher;
} else if (encryptionType === 'reverse') {
encryptionMethod = reverseCipher;
} else if (encryptionType === 'caesar') {
let amount = Number(process.argv[3]);
if (Number.isNaN(amount)) {
process.stdout.write(`Try again with a valid amount argument. \n`)
process.exit();
}
encryptionMethod = (str) => caesarCipher(str, amount);
}
else {
process.stdout.write(`Try again with a valid encryption type. \n`)
process.exit();
}
process.stdout.write('Enter the message you would like to encrypt...\n> ');
return encryptionMethod;
}
/* Helper function for displaying the encrypted message to the user. */
function displayEncryptedMessage(encryptionMethod, userInput) {
let str = userInput.toString().trim();
let output = encryptionMethod(str);
process.stdout.write(`\nHere is your encrypted message:\n> ${output}\n`)
process.exit();
}
encryptors.js
// Declare and export the functions here.
// Encryption Functions
/////////////////////////////////////////////
const caesarCipher = (str, amount = 0) => {
if (amount < 0) {
return caesarCipher(str, amount + 26);
}
let output = '';
for (let i = 0; i < str.length; i++) {
let char = str[i];
if (char.match(/[a-z]/i)) {
let code = str.charCodeAt(i);
if (code >= 65 && code <= 90) {
char = String.fromCharCode(((code - 65 + amount) % 26) + 65);
} else if (code >= 97 && code <= 122) {
char = String.fromCharCode(((code - 97 + amount) % 26) + 97);
}
}
output += char;
}
return output;
};
const symbolCipher = (str) => {
const symbols = {
'i': '!',
'!': 'i',
'l': '1',
'1': 'l',
's': '$',
'$': 's',
'o': '0',
'0': 'o',
'a': '@',
'@': 'a',
'e': '3',
'3': 'e',
'b': '6',
'6': 'b'
}
let output = '';
for (let i = 0; i < str.length; i++) {
let char = str.toLowerCase()[i];
if (symbols[char]) {
output += symbols[char]
} else {
output += char;
}
}
return output;
}
const reverseCipher = (sentence) => {
let words = sentence.split(' ');
for (let i = 0; i < words.length; i++) {
words[i] = words[i].split('').reverse().join('');
}
return words.join(' ');
};
module.exports = {
caesarCipher,
symbolCipher,
reverseCipher
};
super-encoder.js
// Import the encryptors functions here.
const {caesarCipher, symbolCipher, reverseCipher} = require('./encryptors.js');
const encodeMessage = (str) => {
// Use the encryptor functions here.
return reverseCipher(symbolCipher(caesarCipher(str, 6)));
}
const decodeMessage = (str) => {
// Use the encryptor functions here.
return caesarCipher(symbolCipher(reverseCipher(str)), -6);
}
// User input / output.
const handleInput = (userInput) => {
const str = userInput.toString().trim();
let output;
if (process.argv[2] === 'encode') {
output = encodeMessage(str);
}
if (process.argv[2] === 'decode') {
output = decodeMessage(str);
}
process.stdout.write(output + '\n');
process.exit();
}
// Run the program.
process.stdout.write('Enter the message you would like to encrypt...\n> ');
process.stdin.on('data', handleInput);