Jump to content

JavaScript/Syntax examples

From Wikibooks, open books for an open world

These are simple examples of JavaScript syntax.

Variables in JavaScript can be defined using either the var,[1] let[2] or const[3] keywords. Variables defined without keywords will be defined at the global scope.

// Declares a function-scoped variable named `x`, and implicitly assigns the
// special value `undefined` to it. Variables without value are automatically
// set to undefined.
// var is generally considered bad practice and let and const are usually preferred.
var x;

// Variables can be manually set to `undefined` like so
let x2 = undefined;

// Declares a block-scoped variable named `y`, and implicitly sets it to
// `undefined`. The `let` keyword was introduced in ECMAScript 2015.
let y;

// Declares a block-scoped, un-reassignable variable named `z`, and sets it to
// a string literal. The `const` keyword was also introduced in ECMAScript 2015,
// and must be explicitly assigned to.

// The keyword `const` means constant, hence the variable cannot be reassigned
// as the value is `constant`.
const z = "this value cannot be reassigned!";

// Declares a global-scoped variable and assigns 3.  This is generally considered
// bad practice, and will not work if strict mode is on.
t = 3;

// Declares a variable named `myNumber`, and assigns a number literal (the value
// `2`) to it.
let myNumber = 2;

// Reassigns `myNumber`, setting it to a string literal (the value `"foo"`).
// JavaScript is a dynamically-typed language, so this is legal.
myNumber = "foo";

Note the comments in the examples above, all of which were preceded with two forward slashes.

There is no built-in input/output functionality in JavaScript, instead it is provided by the run-time environment. The ECMAScript specification in edition 5.1 mentions that "there are no provisions in this specification for input of external data or output of computed results".[4] However, most runtime environments have a console object that can be used to print output.[5] Here is a minimalist "Hello, World!" program in JavaScript in a runtime environment with a console object:

console.log("Hello, World!");

In HTML documents, a program like this is required for an output:

// Text nodes can be made using the "write" method.
// This is frowned upon, as it can overwrite the document if the document is fully loaded.
document.write('foo');

// Elements can be made too. First, they have to be created in the DOM.
const myElem = document.createElement('span');

// Attributes like classes and the id can be set as well
myElem.classList.add('foo');
myElem.id = 'bar';

// After setting this, the tag will look like this: `<span class="foo" id="bar" data-attr="baz"></span>`
myElem.setAttribute('data-attr', 'baz'); // Which could also be written as `myElem.dataset.attr = 'baz'`

// Finally append it as a child element to the <body> in the HTML
document.body.appendChild(myElem);

// Elements can be imperatively grabbed with querySelector for one element, or querySelectorAll for multiple elements that can be looped with forEach
document.querySelector('.class'); // Selects the first element with the "class" class
document.querySelector('#id'); // Selects the first element with an `id` of "id"
document.querySelector('[data-other]'); // Selects the first element with the "data-other" attribute
document.querySelectorAll('.multiple'); // Returns an Array-like NodeList of all elements with the "multiple" class

A simple recursive function to calculate the factorial of a natural number:

function factorial(n) {
    // Checking the argument for legitimacy. Factorial is defined for positive integers.
    if (isNaN(n)) {
        console.error("Non-numerical argument not allowed.");
        return NaN; // The special value: Not a Number
    }
    if (n === 0)
        return 1; // 0! = 1
    if (n < 0)
        return undefined; // Factorial of negative numbers is not defined.
    if (n % 1) {
        console.warn(`${n} will be rounded to the closest integer. For non-integers consider using gamma function instead.`);
        n = Math.round(n);
    }
    // The above checks need not be repeated in the recursion, hence defining the actual recursive part separately below.

    // The following line is a function expression to recursively compute the factorial. It uses the arrow syntax introduced in ES6.
    const recursivelyCompute = a => a > 1 ? a * recursivelyCompute(a - 1) : 1; // Note the use of the ternary operator `?`.
    return recursivelyCompute(n);
}

factorial(3); // Returns 6

An anonymous function (or lambda):

const counter = function() {
    let count = 0;
    return function() {
        return ++count;
    }
};

const x = counter();
x(); // Returns 1
x(); // Returns 2
x(); // Returns 3

This example shows that, in JavaScript, function closures capture their non-local variables by reference.

Arrow functions were first introduced in 6th Edition – ECMAScript 2015. They shorten the syntax for writing functions in JavaScript. Arrow functions are anonymous, so a variable is needed to refer to them in order to invoke them after their creation, unless surrounded by parenthesis and executed immediately.

Example of arrow function:

// Arrow functions let us omit the `function` keyword.
// Here `long_example` points to an anonymous function value.
const long_example = (input1, input2) => {
    console.log("Hello, World!");
    const output = input1 + input2;

    return output;
};

// If there are no braces, the arrow function simply returns the expression
// So here it's (input1 + input2)
const short_example = (input1, input2) => input1 + input2;

long_example(2, 3); // Prints "Hello, World!" and returns 5
short_example(2, 5);  // Returns 7

// If an arrow function has only one parameter, the parentheses can be removed.
const no_parentheses = input => input + 2;

no_parentheses(3); // Returns 5

// An arrow function, like other function definitions, can be executed in the same statement as they are created.
// This is useful when writing libraries to avoid filling the global scope, and for closures.
let three = ((a, b) => a + b) (1, 2);

const generate_multiplier_function = a => (b => isNaN(b) || !b ? a : a*=b);
const five_multiples = generate_multiplier_function(5); // The supplied argument "seeds" the expression and is retained by a.
five_multiples(1); // Returns 5
five_multiples(3); // Returns 15
five_multiples(4); // Returns 60

In JavaScript, objects can be created as instances of a class.

Object class example:

class Ball {

   constructor(radius) {
      this.radius = radius;
      this.area = Math.PI * ( radius ** 2 );
   }

   // Classes (and thus objects) can contain functions known as methods
   show() {
      console.log(this.radius);
   }
};

const myBall = new Ball(5); // Creates a new instance of the ball object with radius 5
myBall.radius++; // Object properties can usually be modified from the outside
myBall.show();   // Using the inherited "show" function logs "6"

In JavaScript, objects can be instantiated directly from a function.

Object functional example:

function Ball(radius) {

   const area = Math.PI * ( radius ** 2 );
   const obj = { radius, area };

   // Objects are mutable, and functions can be added as properties.
   obj.show = () => console.log(obj.radius);
   return obj;
};

const myBall = Ball(5); // Creates a new ball object with radius 5. No "new" keyword needed.
myBall.radius++; // The instance property can be modified.
myBall.show();   // Using the "show" function logs "6" - the new instance value.

Variadic function demonstration (arguments is a special variable):[6]

function sum() {
    let x = 0;

    for (let i = 0; i < arguments.length; ++i)
        x += arguments[i];

    return x;
}

sum(1, 2); // Returns 3
sum(1, 2, 3); // Returns 6

// As of ES6, using the rest operator.
function sum(...args) {
    return args.reduce((a, b) => a + b);
}

sum(1, 2); // Returns 3
sum(1, 2, 3); // Returns 6

Immediately-invoked function expressions are often used to create closures. Closures allow gathering properties and methods in a namespace and making some of them private:

let counter = (function() {
    let i = 0; // Private property

    return {   // Public methods
        get: function() {
            alert(i);
        },
        set: function(value) {
            i = value;
        },
        increment: function() {
            alert(++i);
        }
    };
})(); // Module

counter.get(); // Returns 0
counter.set(6);
counter.increment(); // Returns 7
counter.increment(); // Returns 8

Generator objects (in the form of generator functions) provide a function which can be called, exited, and re-entered while maintaining internal context (statefulness).[7]

function* rawCounter() {
    yield 1;
    yield 2;
}

function* dynamicCounter() {
    let count = 0;
    while (true) {
        // It is not recommended to utilize while true loops in most cases.
        yield ++count;
    }
}

// Instances
const counter1 = rawCounter();
const counter2 = dynamicCounter();

// Implementation
counter1.next(); // {value: 1, done: false}
counter1.next(); // {value: 2, done: false}
counter1.next(); // {value: undefined, done: true}

counter2.next(); // {value: 1, done: false}
counter2.next(); // {value: 2, done: false}
counter2.next(); // {value: 3, done: false}
// ...infinitely

JavaScript can export and import from modules:[8]

Export example:

/* mymodule.js */
// This function remains private, as it is not exported
let sum = (a, b) => {
    return a + b;
}

// Export variables
export let name = 'Alice';
export let age = 23;

// Export named functions
export function add(num1, num2) {
    return num1 + num2;
}

// Export class
export class Multiplication {
    constructor(num1, num2) {
        this.num1 = num1;
        this.num2 = num2;
    }

    add() {
        return sum(this.num1, this.num2);
    }
}

Import example:

// Import one property
import { add } from './mymodule.js';
console.log(add(1, 2));
//> 3

// Import multiple properties
import { name, age } from './mymodule.js';
console.log(name, age);
//> "Alice", 23

// Import all properties from a module
import * from './module.js'
console.log(name, age);
//> "Alice", 23
console.log(add(1,2));
//> 3

More advanced example

[edit | edit source]

This sample code displays various JavaScript features.

/* Finds the lowest common multiple (LCM) of two numbers */
function LCMCalculator(x, y) { // constructor function
    if (isNaN(x*y)) throw new TypeError("Non-numeric arguments not allowed.");
    const checkInt = function(x) { // inner function
        if (x % 1 !== 0)
            throw new TypeError(x + "is not an integer");

        return x;
    };

    this.a = checkInt(x)
    //   semicolons   ^^^^  are optional, a newline is enough
    this.b = checkInt(y);
}
// The prototype of object instances created by a constructor is
// that constructor's "prototype" property.
LCMCalculator.prototype = { // object literal
    constructor: LCMCalculator, // when reassigning a prototype, set the constructor property appropriately
    gcd: function() { // method that calculates the greatest common divisor
        // Euclidean algorithm:
        let a = Math.abs(this.a), b = Math.abs(this.b), t;

        if (a < b) {
            // swap variables
            // t = b; b = a; a = t;
            [a, b] = [b, a]; // swap using destructuring assignment (ES6)
        }

        while (b !== 0) {
            t = b;
            b = a % b;
            a = t;
        }

        // Only need to calculate GCD once, so "redefine" this method.
        // (Actually not redefinition—it's defined on the instance itself,
        // so that this.gcd refers to this "redefinition" instead of LCMCalculator.prototype.gcd.
        // Note that this leads to a wrong result if the LCMCalculator object members "a" or "b" are altered afterwards.)
        // Also, 'gcd' === "gcd", this['gcd'] === this.gcd
        this['gcd'] = function() {
            return a;
        };

        return a;
    },

    // Object property names can be specified by strings delimited by double (") or single (') quotes.
    "lcm": function() {
        // Variable names do not collide with object properties, e.g., |lcm| is not |this.lcm|.
        // not using |this.a*this.b| to avoid FP precision issues
        let lcm = this.a / this.gcd() * this.b;

        // Only need to calculate lcm once, so "redefine" this method.
        this.lcm = function() {
            return lcm;
        };

        return lcm;
    },

    // Methods can also be declared using ES6 syntax
    toString() {
        // Using both ES6 template literals and the (+) operator to concatenate values
        return `LCMCalculator: a = ${this.a}, b = ` + this.b;
    }
};

// Define generic output function; this implementation only works for Web browsers
function output(x) {
    document.body.appendChild(document.createTextNode(x));
    document.body.appendChild(document.createElement('br'));
}

// Note: Array's map() and forEach() are defined in JavaScript 1.6.
// They are used here to demonstrate JavaScript's inherent functional nature.
[
    [25, 55],
    [21, 56],
    [22, 58],
    [28, 56]
].map(function(pair) { // array literal + mapping function
    return new LCMCalculator(pair[0], pair[1]);
}).sort((a, b) => a.lcm() - b.lcm()) // sort with this comparative function; => is a shorthand form of a function, called "arrow function"
    .forEach(printResult);

function printResult(obj) {
    output(obj + ", gcd = " + obj.gcd() + ", lcm = " + obj.lcm());
}

The following output should be displayed in the browser window.

LCMCalculator: a = 28, b = 56, gcd = 28, lcm = 56
LCMCalculator: a = 21, b = 56, gcd = 7, lcm = 168
LCMCalculator: a = 25, b = 55, gcd = 5, lcm = 275
LCMCalculator: a = 22, b = 58, gcd = 2, lcm = 638

References

[edit | edit source]
  1. ↑ "var – JavaScript". The Mozilla Developer Network. Archived from the original on December 23, 2012. Retrieved December 22, 2012.
  2. ↑ "let". MDN web docs. Mozilla. Archived from the original on May 28, 2019. Retrieved June 27, 2018.
  3. ↑ "const". MDN web docs. Mozilla. Archived from the original on June 28, 2018. Retrieved June 27, 2018.
  4. ↑ "ECMAScript Language Specification – ECMA-262 Edition 5.1". Ecma International. Archived from the original on November 26, 2012. Retrieved December 22, 2012.
  5. ↑ "console". Mozilla Developer Network. Mozilla. Archived from the original on February 28, 2013. Retrieved April 6, 2013.
  6. ↑ "arguments". Mozilla Developer Network. Mozilla. Archived from the original on April 13, 2013. Retrieved April 6, 2013.
  7. ↑ "function* - JavaScript | MDN". developer.mozilla.org. Retrieved 2022-09-27.
  8. ↑ "JavaScript modules". MDN Web Docs. Mozilla. Archived from the original on 17 July 2022. Retrieved 28 July 2022.