Friday, November 29, 2019

JavaScript Functions

Introduction to Functions

Functions are also referred to as subroutine or procedure.

What is a function?

  • a function is a block of code that can be executed or invoked multiple times
  • a function definition contains parameters which are identifiers that work as local variables in the function body

Function Invocation

each function invocation is associated with a number of values:

  • the arguments are the values given to the function parameters
  • the return value is the value of the invocation expression
  • the invocation context is the object that caused the function to be invoked; it is the value of the keyword this

What is a method?

  • an object method is a function that is assigned to an object's property
  • for method invocations the invocation context is the object itself.

Constructors:

  • function designed to create new objects are named constructors.

JavaScript functions are objects that are manipulated by programs:

  • they can be assigned to a variable
  • they can be passed as an argument to a function
  • they can be returned from a function
  • they can be stored in objects or arrays

JavaScript function definition can be nested within other functions

1 Function Objects

JavaScript functions are objects not syntax

functions prototype object

  • every JavaScript object is created with a [[Prototype]] attribute that references a prototype object
  • object created as object literals are linked to Object.prototype, whereas function objects reference the Function.prototype object, which is linked to Object.prototype

functions prototype property

  • function objects (except arrow functions) are created with an additional prototype property, which is distinct from the [[Prototype]] attribute
  • every function object has a different prototype property, which refers to an object, known as the prototype object
  • the prototype object has a constructor property whose value is the function object

what is the meaning of the prototype property?

  • if a function is used as a constructor, the prototype object will be assigned as value of the property [[Prototype]] to all the objects created by that constructor, see constructor functions

2 Defining Functions

You can define a function with:

  • the function declaration (or function statement)
  • the function expression (of function literal)
  • the arrow function expression
  • the Function constructor

Functions with special purpose are:

  • generator functions using the syntax function*
  • asynchronous functions are tagged by the async keyword
2.1 Function Declaration
function name([par_1, ... [, par_n]]){
  statements
}
  • a function declartion expands into a var statement which declare a variable and assigns a function value to it
  • unlike ordinary var statement, both pieces of function statement are hoisted up to the start of script or function

the components of a function declaration statements are:

  • the function keyword
  • a name identifier that names the function
  • the ([par_1, ... [, par_n]]) parameter list enclosed in parentheses
  • the function statements enclosed in curly braces

Examples of function declaration statements:

// Ex.1 function that add two numbers
function sum(num1, num2) {
    return num1 + num2;
}

// Ex.2 factorial recursive function
function factorial(x) {
    if (x <= 1) return 1;
    return x * factorial(x-1);
} 
    
// Ex.3 compare function used as argument to array's sort method
function compare(value1,value2) {
    if(value1 < value2) return -1;
    else if (value1 > value2) return 1;
    else return 0; 
}
var array = [0,1,10,2,20,3,30];
array.sort(compare);
2.2 Function Expressions

Function definition expressions appear in larger expressions or statements

function [funcName]([par_1, ... [, par_n]]){
  statements
}
  • a function literal creates a function object, like an object literal creates an object

Examples of function expression

// Ex.1 anonymous function or function expression without name. 
const sum = function(num1, num2) { // declare a variable named sum and assign
    return num1 + num2;          // the variable with a function expression 
};
    
// Ex.2 named function expression
// Since it's difficult to debug an anonymous function it's best to add a name.
const sum = function sum(num1, num2) {
    return num1 + num2;
};
    
// Ex.3 factorial recursive function expression
// When the name is present that name can be used by the function to call itself recursively
const factorial = function recursiveFactorial(x) {
    if(x<=1) return 1;
    else return x * recursiveFactorial(x-1);
};

// Ex.4 function expression used as argument to array's sort method
var array = [0,1,10,2,20,3,30];
array.sort( function(num1,num2) { return num1-num2; } );
    
// Immediately Invoked Function Expressions (IIFE) are anonymous functions wrapped 
// in parentheses and auto-invoking.
    
// Ex.5 use an IIFE to invoke a function and store result of the invocation in a variable
var twoPlusTwo = (function sum(num1, num2) { return num1 + num2; }(2,2));
    
// Ex.6 use an IIFE as a namespace to avoid local variable conflicting with global variable.
// Variables i and k will never clash with other variables with same name
(function(i) {
    for(var k=0;k<i;k++) {
        console.log("k = "+k);
    }
}(3));

Function expressions names

  • add a name to function expressions that need to refer to themselves
  • if a function definition expression includes a name, the function name becomes a local variable within the function: a variable bound to the function object

Function statements vs function expressions

  • function statements always have a function name, whereas function expressions usually omit the name
  • function statements declare a new variable and assign a function object to it, whereas function expressions only create a function object
  • function defined by statements can be invoked from code that appear before they are defined. This is due to function hoisting
  • functions defined by expressions cannot be invoked before they are defined. This is due to the fact that variable declarations are hoisted, but assignments to variables are not hoisted.
2.3 Arrow Functions Expression

ES6 introduces a new syntax for function expression known as arrow function

  ([par_1, ... [, par_n]]) => { statements }
  • this syntax does not use either a function keyword or a function name
  • this syntax has a list of parameters enclosed in parentheses, followed by the fat arrow (=>) and by the function body enclosed in curly braces

Arrow function compact form

  • if the body of the function contains a single return statement, you can omit the return statement, semicolon and the curly braces.
  • the compact form is commonly used to pass a function to another function
  • if the arrow function has only one parameter, also the parenteses can be omitted
  • if the arrow function returns an object, it has to wrap the function body in parenthesis ( )

Example: arrow functions

// arrow function syntax
const sum = (x, y) => { return x + y; };
// arrow function syntax in compact form
const sum = (x, y) => x + y;
// arrow function with only one parameter
const greeting = name => 'hello from ' + name; 
// arrow that uses parentheses to return an object
const car = () => ({ id:1, make:'Jeep', model:'Renegade, color:'gray' })

Example: arrow functions for passing a function as argument

// make a copy of an array with null elements removed
const filtered = [1, null, 2, 3].filter(x => x !== null); // [1,2,3]
// square some numbers:
const squares = [1, 2, 3, 4].map(x => x*x);               // [1,4,9,16]

Arrow functions compared to ordinary functions

  • arrow functions do not define their own invocation context
  • they inherit the this value from the environment where they are defined
  • they do not have a prototype property, so they cannot be used as constructor function for new classes
2.4 Nested Functions

Functions can be nested within other functions

  • variable scoping: nested function can access variables and parameters of the outer function

3 Invoking Functions

You can invoke a JavaScript functions:

  • as functions
  • as methods
  • as constructors
  • indirectly through call() and apply() methods
3.1 Function Invocation

How to invoke a function:

  • you can invoke functions, as functions or as methods, by using an invocation expression
  • an invocation expression consists of an expression that evaluates to a function object followed by a list of argument expressions between parentheses
  • if the function expression accesses a property of an object, then the invocation expression is a method invocation

Example: function invocations

 let total = sum(1,2) + sum(3,4); 
 // combinations of n items with r chosen = n! / (r! * (n - r)!)
 let _10C3 = factorial(10) / (factorial(3) * factorial(10 - 3)); // 120
  • in a function invocation, the argument expressions are evaluated and the values produced by the argument expression are assigned to function's parameters
  • in the body of the function, a reference to a parameter evaluates to the argument value

What is the value of a function invocation expression?

  • the value returned in the function body becomes the value of the function invocation expression
  • the function returns when the interpreter reaches the end or when the function executes a return
    • in the former case the return value is undefined
    • in the latter case the return value is the value returned by the return statement.

Function's invocation context

  • the invocation context is the this value
    • in non-strict mode, this points to the global object
    • in strict mode, this evaluates to undefined
    • note: functions designed to be invoked as function not as method, do not use the this keyword
  • arrow functions have lexical scope, they do not create their own invocation context
    • this points to the enclosing context where they are defined
3.2 Method Invocation

Invoke an object method using the invocation expressions below:

 obj.method();            // without arguments  
 obj.method(a);           // with one argument
 obj.method(a,b,c,...,N); // with N arguments
  • the method invocation contains a function expression and any number of argument expressions
  • the function is invoked as a method, because the function expression accesses an object property

Method invocation compared to function invocation

  • arguments and return value work the same for method and function invocations
  • method invocations differ from function invocations in the invocation context
    • the method's invocation context is the object
    • in the method body, your code can refer to the object by using the this keyword

Example: using the this keyword in the method body

const person = {
    height: 1.80, // height in metre
    mass: 70, // mass in kg
    calculateBMI(){ // calculate the body mass index
        // note the use of this to refer to the containing object
        this.bodyMassIndex = this.mass / (this.height * this.height);
    }
}
person.calculateBMI(); // method invocation
person.bodyMassIndex; // 21.6

Note: this is a keyword not a variable, you cannot assign a value to this

What is the value of this in nested functions?

  • the scope of the this keyword is not the same as the scope of variables declared by let keyword:
    • ordinary nested functions do not inherit the this value from the containing function
    • only arrow functions inherit the this value from the containing function
  • if a nested function is invoked as function, the this value is either undefined in strict mode or the global object in sloppy mode
  • if a nested function is invoked as a method, the this value is the object it is invoked on
3.3 Constructor Invocation

a constructor invocation is function invocation preceded by the keyword new

  • constructor invocations differ from regular functions in the way they handle arguments, invocation context and return value

Example: constructor invocations

 let object = new Object();
 // a constructor invocation may include an argument list
 let birthday = new Date('1983-11-12T03:24:00')

a constructor invocation creates a new object

  • the new object uses the value of the prototype property of the constructor function as its prototype
  • the invocation context is the new object, you can use this keyword to initialize the new object

What is the value of a constructor invocation?

  • constructor functions do not use the return keyword
  • the newly built object is the value of the invocation expression
3.4 Indirect Invocation

JavaScript functions are objects and have two methods that allow functions to be invoked indirectly

  • the call() and apply() function's methods invoke the function indirectly
  • these methods allow to invoke the function as method of an object passed as argument
  • both methods allow to specify the arguments for the invocation

No comments:

Post a Comment