TypeScript Functions



Headlines
JavaScript Functions

JavaScript functions are first-class language' elements in the sense that they are plain objects. Function is the constructor (i.e., runtime type) of function objects.

Rule(s)

const f = function () { /* <=> 'return;' <=> 'return undefined;' */ };
console.assert(f instanceof Function);
console.assert(typeof f === 'function');
console.assert(f.constructor === Function);

Example

const my_function = function (my_parameter) {
    // Forbidden in strict mode (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments):
    // console.log(arguments.callee);
    return ++my_parameter;
};
console.log(my_function(0)); // '1' is displayed...

Arguments' default values

Rule(s)

Example

// 'Run' as a static function in a class:
static Run(name = "FranckBarbier", job = "Trainer") { …

Anonymous functions

Rule(s)

Example

const f = function (g) { // 'f' is defined...
    console.log("'arguments' is a predefined array that lets the access to the passed arguments: " + arguments.length);
    g();
};
f(function () { // 'f' is called with anonymous function as single argument...
    console.log("This no-name function plays the role of 'g' in 'f'");
});

Lambda expressions

Rule(s)

Example

const f = (g, i = 0) => { // 'f' is defined by means of a lambda expression
    console.log(g(i));
};
// Calling f...
f(function (my_i) { // 'f' is called with an anonymous function as parameter
    return ++my_i;
}/*, 1*/);
// Calling f, another style...
f(my_i => { // 'f' is called with a lambda function as parameter
    return ++my_i;
}/*, 1*/);
// Calling f, yet another style...
f(my_i => ++my_i/*, 1*/); // Implicit 'return'

Variable number of arguments

Rule(s)

Example

const h = function (a = -1, ...bs /*, c*/ /* <- error! */) {
    let sum = a;
    bs.forEach(b => {
        console.log("b: " + b);
        sum += b;
    });
    console.log("Sum: " + sum);
};
// Note that default value for 'a' is useless:
h(1, 2, 3); // 'Sum: 6' is displayed, i.e., '1' is substituted for 'a'
h(...[1, 2, 3]); // <=> 'h(1, 2, 3);'

Rule(s)

Example Lottery.ts.zip 

class Lottery {
    public static Draw(bonus_number: number, ...numbers: Array<number>) /* Return type is inferred... */ {
    …
}
…
let result = Lottery.Draw(6, 43, 12, 3, 32, 34, 22);
console.assert(result.draw[0] === 43);

Meta-functions

Rule(s)

Example

const her_function = function (her_parameter) {
    console.log("'this': " + this + " 'her_parameter': " + her_parameter);
    // Forbidden in strict mode (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/arguments/):
    // console.log(arguments.callee);
};
// First arg. plays the role of 'this' inside the function while '0' is substituted for 'her_parameter':
her_function.call("Catherine", 0); // "'this': Catherine 'her_parameter': 0" is displayed...
// First arg. plays the role of 'this' inside the function while '[0]' is a one-element array containing '0' as unique element:
her_function.apply("Catherine", [0]); // "'this': Catherine 'her_parameter': 0" is displayed...

Generator functions

Rule(s)

Example Generator.ts.zip 

// 'Meal' type has a method named '@@iterator' ('Symbol.iterator' <=> '@@iterator'), which is a generator function:
type Meal = {
    when: string, taste: string,
    [Symbol.iterator](): IterableIterator<string>
};

const meal: Meal = {
    when: "today", taste: "medium",
    [Symbol.iterator]: function* (from = "yesterday") { // Key 'Symbol.iterator' (i.e., '@@iterator') is added as 'Generator' object
        yield from;
        yield "today";
        yield "tomorrow";
    }
};
const {when: first_part, ...remaining_part} = meal;
console.info(first_part); // 'today'
console.info(JSON.stringify(remaining_part)); // '{"taste":"medium"}'

console.info(Object.getOwnPropertySymbols(meal)[0] === Symbol.iterator); // 'true'

const iterator: IterableIterator<string> = meal[Symbol.iterator]();
console.info(iterator.next().value); // 'yesterday'

// Spread syntax only applies on iterable objects (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax):
console.info([...meal]); // '[ 'yesterday', 'today', 'tomorrow' ]'

for (const value of meal)
    console.info(value); // 'yesterday' 'today' 'tomorrow'

The case of this

Rule(s)

Example (PURE JavaScript)

const o = {};
Object.defineProperty(o, "simple_array", {
    value: [null, 0, "ABC"],
    enumerable: true,
    configurable: true,
    writable: true
});

o.simple_array_processing = function () {
    for (let i = 0; i < this.simple_array.length; i++)
        this.simple_array[i] = null; // Great, 'this' is set to the appropriate "current" object, i.e., 'o'!
};
o.simple_array_processing(); // Call...
console.log(JSON.stringify(o.simple_array)); // '[null,null,null]'

o.simple_array_processing = function () { // Erase prior version...
    this.simple_array.forEach(function (element) {
        console.assert(this !== o);
        console.log("What is 'this'? " + Object.getOwnPropertyNames(this).join(" - "));
    } /* ,this */); // Uncommenting leads to 'this === o'
};
o.simple_array_processing(); // Call...

o.simple_array_processing = function () { // Erase prior version...
    this.simple_array.forEach(element => { // 'this' in lambda expression is set *IN A STATIC WAY*
        console.assert(this === o);
        console.log("What is 'this'? " + Object.getOwnPropertyNames(this).join(" - "));
    } /* ,this */); // No need of injecting 'this' as second argument of 'forEach'
};
o.simple_array_processing(); // Call...

Rule(s)

Example (PURE JavaScript)

const my_iteration = function (element) {
    console.assert(this === o);
    console.log("What is 'this'? " + Object.getOwnPropertyNames(this).join(" - "));
};
o.simple_array_processing = function () { // Erase prior version...
    this.simple_array.forEach(my_iteration.bind(this));
};
o.simple_array_processing(); // Call...