Introduction to Functions

An introduction to JavaScript functions and their uses.

Objectives

At the end of this chapter you will learn to :

  • Define all different kinds of functions
  • Distinguish between an statement and the expression
  • Handle functions from JS perspective
  • Invoke functions directly and indirectly
  • Understand how functions inherits properties too
  • Appreciate functions role in object creation
  • Explore the power of functional programming

Introduction to JavaScript Functions

They are main building blocks of JavaScript, usually assigned a name so that they can be used time and time again by identifying with the given name.They are self-contained modular units.The structure of the function is shown below.

1function functionName() {
2  //code goes here
3}

Defining a function

In order to use a function in your program it needs to be defined so that the JavaScript interpreter knows its existence. Creating a function Unlike “C” programming language does not require it to be declared on the top of the file and then defining separately. In JavaScript a function declaration also defines a function.

Note: The function declaration is not the only way of defining a function. A function expression can also be used to define a function.

Function declaration and function expression

A function key word is used to define a function along with its name and zero or more parameters list followed by the series of statements enclosed within the curly brackets { } known as code blocks or function body, like function fn() { }.

The name of the function depends how you declare a function , the name acts like a label so that you can use a particular function by identifying it from its label thus the name is known as identifier. Function name or identifier has to follow some rules { Syntax rules,Good practice rules, etc } They are case sensitive thus ( do, Do , DO and dO ) are all different.

Just like variable names, the name can have alpha numeric value [0 to 9 and a to z / A to Z]OR _ , $ and special characters. But it can not start with the numbers [0-9] or any keywords and can not contain spaces. If in doubt check it out

After parenthesis, a function starts with a curly brackets { and ends with it }.a pair of curly brackets { } are also known as code blocks or the body of the function. A semicolon is not needed after the end code block }; if it is only a function declaration. The actual code, a series of statements are written inside the curly brackets.

1// declaring a function also  known as function declaration
2function fn() {
3  console.log('Welcome To JavaScript!')
4}

There are four requirements to define the function:

  1. use function keyword, which is must
  2. use of function identifier, which is optional
  3. use of parenthesis ( ) which is must but parameter list inside the parenthesis is optional
  4. use of code block { } which is also must, where the actual code resides.

Note: A function should not be defined inside any conditionals like if and else and they can not appear inside of loops or any try , catch and finally block. This only applies to a function declaration . A function expression may appear anywhere in the code. Function defined in conditional blocks will give unexpected result because of the hoisting .

 1//file-name:chap-02-10.js
 2;(function () {
 3  if (false) {
 4    //function declaration will be hoisted
 5    function doThis() {
 6      console.log("shouldn't be executing")
 7    }
 8  } else if (false) {
 9    // function expression are not hoisted
10    var doThat = function () {
11      console.log('nothing to log')
12    }
13  } else if (true) {
14    // function expression invoked immediately
15    ;(function () {
16      console.log("don't doThis! doThat")
17      doThis()
18      //doThat(); Error not a function
19    })()
20  }
21})()

If a function is given a name fn, this function is also known as a named function as compared to the un-named function, as used in following example.

1 function () {
2  console.log (" Hello and Welcome to the functional language!");
3 }

The above code also fulfils the required conditions except that it does not provide this function a name, hence called anonymous function. using a function is a two step process. The function definition is the first step towards using this function. In order to execute this code the second step is to call this function from somewhere within your program. This process of calling a function is commonly referred as invoking a function. Before we start talking about this second part, the following code block gives you a detailed structure of a function definition.

Structure of a function declaration

 1    Key word
 2        |     Unique function Name known as function identifier
 3        |       |    (0 or more , optional parameters list)
 4        |       |          |
 5        V       V   _______V_____
 6    function name (param1 , param2) {   <----Starting code block
 7        // adding passed arguments   <-----Single line comments
 8        var result = param1 + param2; <----An expression
 9        return result ;           <--------- return statement
10        // A statement after return is never executed.
11        console.log("I will never be reached");
12    };//semi colon not necessary  when declaring a function

As mentioned before, there may be more than one function present in your JS file known as source file, the order does not have any importance. If you have ten or more function declared in your source file, they are treated equally. But function expression does make difference where it has been placed in your programme. Execution of a programme consist of two phases, first one is parsing the code file and second executing the code.

During the first process of parsing , variables and function declaration are hoisted ( are treated as they are written at the top of the file known as lifted up ) and kept separately with the list of parameters being passed.

The second phase is to execute the code keeping the above information in hand. JS does this process so that the engine knows about the existence of variables and functions , no matter where they are declared. And can identify them before the actual code is run, otherwise it would complain as an error if used first and declared later. But this is not the case with function expression, in function expression only the variable declaration part is lifted up, the actual assignment happens at the run time, thus if called first , the engine will say it is not a function but a variable because it is only aware of its declaration not the assignment. In contrast to this, a mere anonymous function is not at all hoisted. An anonymous function is evaluated where it is situated.

Note: Functions can be defined inside other functions known as nested functions. Each consecutive function defined in another function has access to its outer function variables except the this keyword. If this needs to be accessed it should be copied first outerThis = this.

Functions in JS are also objects

Whenever a function either named or unnamed is created. It is created like any other object. It has its own constructor and like other objects it has its prototype to share the behaviour. Since most of the time a programmer is creating a function in one way or another it is best to know more about function object and its prototype so that pre written code can be used as its own. First of all, keep in mind that mere function declaration is enough to create a function object. The declaration creates / calls the Function constructor Function() internally and return an object of type function which is referred by its identifier.

 1function fn() {
 2  return
 3} // fn is now an object of type function
 4console.log(fn.constructor) //[Function: Function]
 5console.log(typeof fn) // function
 6console.log(Object.getPrototypeOf(fn)) //Function( Function.prototype)
 7var myProto = Object.getPrototypeOf(fn)
 8console.log(Object.getPrototypeOf(myProto)) //{} . it is an object too
 9console.log(JSON.stringify(Object.getOwnPropertyNames(myProto)))
10/*["length","name","arguments","caller","constructor","bind","toString","call","apply"]
11 In line no 2 the constructor property was used on function object as if it was its own but, it was inherited through prototype chain from Object.prototype` object.
12 */

A function, being an object is also created with a special function called constructor function Function(). The newly created function also has its prototype name Function.prototype. This prototype provides the services that every instance of Function can share. Thus commonly used properties of a prototype are length,name,arguments while call , apply , toSrring are commonly used methods. Having said that it is also necessary to understand that function ( with capital F ) represent the Function object just like other fundamental objects in JS environment e.g.,Object,Array etc.

If a function is assigned to the property of an object it is called a method of that object. When this method is invoked through this object obj.method then that particular object is the invocation context of this method represented by the keyword this. When this is used inside a method it represent the object that invokes this method.

Another example of creating an implicit Function object when function are created

 1function Animal() {}
 2Animal.prototype.eats = true
 3var kangroo = new Animal()
 4var rabbit = new Animal()
 5console.log(kangroo.eats) //true
 6console.log(rabbit.eats) //true
 7console.log(kangroo.constructor) //Animal
 8console.log(kangroo.__proto__) //Animal{eats:true}
 9// a function can also be added
10Animal.prototype.moves = function (steps) {
11  console.log('moved ' + steps + ' steps')
12}
13kangroo.moves(4) //moved 4 steps

The above code shows another way of creating object using function objects. Whenever a function is created it is assigned a property called prototype this property is used to assign this function object a new property called eats. Then two instances of Animal are created both of them get their individual copy of properties. Note the use of constructor and .__propto__ properties inherited and what they returns

Calling or invoking a function

There may be only one function which exist in the source file, or this piece of code may exist with other function definitions. Writing a function definition is not enough. In order to use the function, it must be called or also known as invoked, either explicitly or implicitly. To call the function, its identifier is used to identify it among other functions. It is just like calling someone’s name to get his/her attention. Though you may get his attention yet he/she will not do what you would want him to do unless you specifically mention what needs to be done.

Therefore by writing the function’s name, as in above case fn, will correctly identify the function but this will not invoke the function unless you specifically use the command to carry out the function. In other words, using an identifier is not enough, it will only pick up the right function among others present in your source file. To carry out this function you have to make use of parenthesis (), therefore the full command of invoking a function would be fn () . It is this pair of parenthesis which execute the function.

Note:Without the pair of parenthesis, the function name only identify the function. To execute the function it must be followed by a pair of parenthesis.

1// trying to invoke without the parenthesis
2fn // nothing would happen,
3console.log(fn) // would print out the fn dedclaration

Directly invoking function declaration

look at this full example in action.

 1// declaring a function
 2function fn() {
 3  console.log('Welcome To JavaScript!')
 4}
 5// invoking a function
 6fn()
 7//it can also be done by assigning it to any variable
 8var f = fn
 9f() // same as fn()
10// trying to invoke without the parenthesis
11fn // nothing happens
12// console.log("The function identifier 'fn' point to --> " + fn);
13// logs  function declaration statement

The above example shows how to invoke a named function, in other words a named function was invoked explicitly. But how an unnamed function would be executed. An unnamed function or an anonymous function differs from the normal named function. Since it has no named it is not possible to invoke it using the above method unless there is some other way exist to invoke it or you may assign it to a variable so that it can act as its identifier. The process of assigning it to a variable has to be done at the same time when writing it, otherwise we have no way to access it. Following examples shows the later scenario first.

1 // declaring an anonymous function
2 function () {
3  console.log ("Welcome to Function Expression");
4 }
5
6 // trying to  assign it to any variable so that it can be referenced
7 var anyVariable = ?

Not possible, declaring an anonymous function and assigning it to a variable must be done at the same time.

1// Function expression,
2var fn = function () {
3  console.log('Welcome to function expression')
4}
5// it can be invoked just like a named function.
6fn() //undefined
  • An anonymous function can have parameters as well
1var fn = function (name) {
2  console.log('Welcome back : ' + this.name)
3}

Function invocation inside another function

The built in functionconsole.log() expects some values as an argument to log or display onto the console. This value can be a function call as done in above example console.log(fn()). This tells us that function accepts other functions to be passed as an argument in the above case what is logged is the function fn() returned value,if no value is returned explicitly the interpreter assigns it undefinedas it happened in the above example.

Indirectly invoking a function

Functions can be invoked indirectly using a built in function provided by the JavaScript knowns as apply and call.

1function fn() {
2  fn.call() // call itself
3}
4// it will create infinite loop and will result in maximum call stake

The use of these method comes handy when you want to provide the execution context explicitly. In Object Oriented Programming when a method of any object is invoked. It is said to be invoked upon this object by passing a special pointer known as this. This pointer knows what it refers to and it is the object that invokes the method. But if you have a function that you would want to invoke by different context then these two methods allow you to do this task.

1var bike1 = { make: 'Honda', year: '1992' }
2var bike2 = { make: 'Yamaha', year: '1980' }
3// what this refers to is not known until it is invoked
4function showDetail() {
5  console.log('This is ' + this.make + ' from ' + this.year)
6}
7showDetail() // unexpected answer

Ideally the function showDetail() should have been the part of the singleton object so that it can be invoked on that object. But since it is not. Let’s see how to use this function. If you invoke showDetail() in global context. The keyword this refers to global object which will try to see if it has any property make if it finds it, fine otherwise it will say undefined. This global object is also depends upon the host environment where you are running this programme. To solve this issue you can take the help of apply and call methods both do the same job except apply takes arguments in an array form, while call takes arguments individually. By using apply or call method you are providing your helper function the scope for this keyword

1var bike1 = { make: 'Honda', year: '1992' }
2var bike2 = { make: 'Yamaha', year: '1980' }
3
4function showDetail() {
5  console.log('This is ' + this.make + ' from ' + this.year)
6}
7showDetail.call(bike1) // invoked with bike1 context
8showDetial.apply(bike2) // invoked with bike2 context

The difference b/w apply and call function

They both do the same job except that apply() takes an array of argument as its second parameter while call() expects individual arguments to be passed to it.

1 function think(name,subject,time){
2  console.log(this.anme + " is thinking about " + subject + " for " + time " seconds");
3 }
4 var dog = {name:"Elsession",food: "pedigree", age: 10 };
5 var boy = { name:"Tonny", age:5};
6 think.call(dog,"bone",10);
7 think.apply(boy,["football,20"]);

Another place where apply and call is used when calling a function which requires an empty object so that the result can be stored in it. Following example shows the use of call method to see how many times a particular number is repeated in an array.

 1function frequency(arr) {
 2  var thisp = this
 3  arr.forEach(function (element) {
 4    thisp[element] = (thisp[element] || 0) + 1
 5  })
 6  return thisp
 7} // End of frequency
 8// calling the function with the accumulator object
 9console.log(frequency.call({}, [1, 2, 3, 4, 3, 2, 1, 3, 4, 5, 3, 21]))
10// { '1': 2, '2': 2, '3': 4, '4': 2, '5': 1, '21': 1 }

Function always returns a value

It should be noted that unlike other languages javaScript functions always return some value even when you do not use return keyword. In above examples whether it is a function declaration or a function expression there is always a returned value. To see what is returned, lets look at the following code.

1 var returnedValue;
2 returnedValue = fn(){ };
3 console.log ( returnedValue); // undefined.
4 /*
5 The above can be written in one line.
6  */
7 console.log (fn());// undefined.

If a function simply don not use the return statement or use it, but does not return any value specifically, in both case a default value of undefined is retuned

 1function fn1() {
 2  console.log('I do not return anything explicitly')
 3}
 4console.log('function fn1() returned value is : ' + fn1()) // undefined
 5// or
 6var fn2 = function () {
 7  console.log('I do not return anything either')
 8  return
 9}
10console.log('This function returned value is also :' + fn2()) // undefined

The following example shows three different ways where an undefined value is returned.

1function someFunction() {
2  console.log('no explicit return') // undefined is retuned implicitly by default
3  //or
4  return undefined // an explicit returned
5  //or
6  return // an implicit value is returned by default undefined
7}

Same function can be used to return different values

Since a function can be assigned inside another function. This can be done in a following manner.

 1function squareOf(num1, num2, num3, num4, num5) {
 2  // Actual function that does the job and return the value
 3  worker = function (number) {
 4    return number * number
 5  }
 6  var result = ''
 7  result += worker(num1) + ' , '
 8  result += worker(num2) + ' , '
 9  result += worker(num3) + ' , '
10  result += worker(num4) + ' , '
11  return result
12}
13console.log(squareOf(10, 20, 30, 40, 50))

The above can be done in more elegant way.

 1function squareOf(num1, num2) {
 2  worker = function (number) {
 3    return number * number
 4  }
 5  var result = ''
 6  for (var i = 0; i < arguments.length; i++) {
 7    result += worker(arguments[i]) + ' , '
 8  }
 9  return result
10}
11console.log(squareOf(23, 45))

Function expression

When a function is assigned to any variable like a value, it becomes the function expression. The function can be named or unnamed function as shown below. Invoking a function is possible in a same way as done with named function providing trailing brackets.

 1//  Un named function expression,
 2var fn1 = function () {
 3  console.log('Welcome to un named function expression')
 4} // semi colon in must
 5fn1()
 6// Named function expression good for debugging
 7var fn2 = function fn() {
 8  console.log('Welcome to named function expression !')
 9}
10// it can be invoked by either identifier.
11fn2()

Once an anonymous function is assigned to any variable, it can be invoked using that handle in a same fashion as a named function.

Difference between function declaration and function expression

When invoking either function declaration or function expression they look same but there is a difference. In case of function declaration The call to invoke a function always succeed because JavaScript variables and functions declaration are hoisted.

1console.log(' Calling before declaration : ' + fn())
2function fn() {
3  console.log('below')
4}

But in case of function expression the result will be different. For the simple reason that an expression requires some evaluation and that evaluation only happens when the code is run. Thus in defining the function expression its declaration part is hoisted, but not the assignment. Thus engine would not throw an error of not identifying the variable but it will throw an eroor of type TypeError about its use as shown below.

1console.log(' I am called first : ' + fn())
2var fn = function () {
3  console.log(' below ')
4}
5// TypeError: fn is not a function,

Therefore always use the good practice rules, define first use next whether it is a function declaration or function expression.

Immediately invoked function

When dealing with anonymous function, they can be made self executable so there is no need of invoking it explicitly. As we know that, to execute a function you need a handle to it which is required by means of its name or identifier. Once a handle or reference is achieved to any function, it can be invoked by adding a pair of parenthesis at the end. Thus by using the same logic, a self execution can be achieved at the time of writing an anonymous function.

 1 // anonymous function
 2  function () { console.log ( "I am a self executable");}
 3
 4 /* enclose  the whole function within a parenthesis so that it can be identified as one unit*/
 5 // here a pair of parenthesis is acting as a wrapper to function.
 6 (function(){console.log ( "I am a self executable");})
 7
 8 //now the above line of code can be run easily followed by `()`
 9 (function(){console.log ( "I am a self executable");})();
10
11 /* it is same as writing an anonymous function and assigning it to any variable and then using the identifier to invoke the function. as shown below */
12 var fn = function () { console.log ( "I am self executable ") ;}
13 fn();
14
15 // another style of writing the above
16 (function(){console.log("I am a self executable");}());

The above is an an example of what is commonly known as IIFE pronounced iffe and stands for immediately invoked function expression. In JavaScript anonymous function and IIFE plays great role when writing code. There are number of JavaScript libraries exist that make use of IIFE and anonymous function frequently. As the name suggests they are not required to be invoked. They are invoked automatically as they are expression , if list of parameters is defined they can also accept the arguments passed to them. Following describes its skeleton

1;(function (param1, param2) {
2  // code
3})(1, 1)
4//The above is same as below
5;(function (param1, param2) {
6  //code
7})(2, 2)

For any function identifier or a function expression to be invoked the existence of parenthesis with or without arguments are must. Both positions shown above will work. It should be noted that variable defined inside the immediately Invoked function expression are private to this function and are not available from outside.

Use of IFEE

An IIfE can be used to get the private counter to keep track of some task performed.

Passing arguments to Immediately invoked functions

JS is said to have functional programming features and one of them is to return a function and accept function as an argument. When accepting as an argument, it can be defined inside another function.

1;(function (capital, country) {
2  console.log(country + "'s capital is :" + capital)
3})('London', 'England')

Or using other style, where a pair of parenthesis are written inside the wrapper.

1;(function (petrol) {
2  var result = petrol * 40
3  console.log(
4    'Toyota Hybrid  will run for :' + result + ' miles in ' + petrol + ' litres'
5  )
6})(2)

It is also not common but acceptable to pass another function when function is invoked even when dealing with IIFE.

1;(function (factory) {
2  console.log(factory.name)
3  console.log(factory.length)
4  console.log(factory.arguments)
5  console.log(factory.constructor)
6})(function (x, y) {})

Functions can accept other functions as an arguments

Just like passing any object as a parameter to any function is allowed and legal so does passing a function too. When passing functions to other functions occurs which is a normal behaviour when complexity grows, functions act like other values and behave as data. Below is forEach() function which accepts the first argument as a function. You can either define the function inside the forEach() function or define it separately and pass its identifier as shown below:

1 var arr = [1,2,3,2,1,23];
2  function callback(){console.log("I am called on each array item";)}
3  arr.forEach(callback);
4  // or define it within the function
5  arr.forEach(function(element){
6              console.log("I am called on each element " + element);
7  });

Another example of passing function as an argument

1function fn(value, callback) {
2  console.log(value) //30;
3  console.log(callback) // undefined
4}
5fn(30)
6// you can define it separately
7// function callback(parm){
8//
9//      }

The above code can now be changed slightly to make callback parameter points to a function definition which is done when a function is invoked.

 1function fn(value, callback) {
 2  console.log(value) //10;
 3  console.log(callback + '') // prints callback function
 4  return callback(value)
 5}
 6// callback function is defined when calling a function
 7fn(30, function (number) {
 8  if (number >= 10000) return number
 9  return arguments.callee(number)
10})

Callback Function

When a function A is passed to another function B and B executes A then A is known as callback function.

  • function A does not need to have a name , it is regarded as an anonymous function. A callback function can be defined separately and passed a reference to the function that executes it. Or it can be defined within the argument of an executing function below is another example of callback function.
 1
 2    function reverse(arr,callback){
 3        var result = callback(arr);
 4        return result;
 5    }
 6
 7    var result = reverse([1,2,3,4],function(arr){
 8                for(var i = 0; i<arr.length; i++){
 9                    var temp =
10                }
11        })

Parameters and Arguments

To be able to accept the arguments, function declaration must define its parameters, they are written inside pair of parenthesis by a comma separated values (param1,param2,…..).These parameters are only available inside the functions. Being available inside the function means that these values can be accessed and manipulated and act as local variables.function fn(a,b){return a+b;}

When you define any function you are expected to provide the parameter list so they can be used within that function by accessing them with the listed names. but unlike other languages in JavaScript specifying the parameters aren’t necessary and even if specified they don’t need to match the number of arguments being passed to the function.

1function fn(name, age) {
2  console.log('name is :' + name + '\t age is :' + age)
3}

The above function expects two arguments to be passed when it is invoked. But if none is provided, there will be no errors. JavaScript will assign them a primitive data type, as discussed before , undefined. Therefore you are allowed to pass any number of arguments. Those which matches with the parameters gets its value and the rest are assigned default values. Thus you may invoke the function fn() without passing any arguments or passing only the one you want and it will produce no error, like fn("Sayyed") . Similarly if you provide more arguments than expected the superfluous arguments will be ignored.

Note:If you are coming from C++ or Java or any other language, you may be wondering that this is not what you would do in other languages that is known as function polymorphism. In JavaScript there is no function polymorphism.

arguments object

Unlike other languages in JavaScript specifying the parameters aren’t necessary and even if specified they don’t need to match the arguments being passed. When a function is invoked it is given an array like object named arguments by default. This object is used to access the arguments passed to the function, like arguments[0] to accesses the first arguments passed to the function and so on.

1//file-name:chap-02-11.js
2function fn() {
3  for (var i = 0; i < arguments.length; i++) {
4    console.log('arguments are :' + arguments[i])
5  }
6}
7fn(1, 2, 3, 4)

In above example, a function was called with four arguments but it was not mapped with the parameter list at the receiving end. Thus the array object arguments is used to access them inside the function because there was no parameter list defined.

If a parameter is defined and function is invoked with the same number of argument they both are correctly mapped with each other. Thus changing either of them effects the other one as shown below.

1function fn(value) {
2  console.log(value) // 5
3  console.log(arguments[0]) // 5
4  value = 10 // value is changed
5  console.log(arguments[0]) // 10 ,it gets changed too
6  arguments[0] = 100 // arjuments[0] contents changed
7  console.log(value) // value is also changed
8}
9fn(5)

Note: A common practice to check if any argument is passed or not when a function is invoked to check the length of the coming arguments. If no argmunets are passed then work is not done other wise carry on as explained below

 1Metalsmith.prototype.directory = function (directory) {
 2  if (!arguments.length) return path.resolve(this._directory)
 3  assert(is.string(directory), 'You must pass a directory path string.')
 4  this._directory = directory
 5  return this
 6}
 7/*
 8 It is a common practice to write " if without a block if there is only one expression "
 9 if(success) do a;
10 otherwise do b.
11 The test if(!argument.length) can be read like if arguments length is not zero then do a or in above case "return path.....""
12 otherwise assert and follow the rest
13 */

Note: Only write one statement in a line if more than one statement use if block

Assigning Default Values to the Parameters

There are number of occasions when a function is expected to provide default values to the function parameters if no arguments are passed or the parameters are undefined. The following two approaches are good ways to provide default values

 1    function addDetail(fname,lname,gender,title){
 2        //some code
 3        if(title === undefined && gender === "male") title = Mr.
 4    } addDetail("Mike","Rossen","male");
 5    // another approach
 6    function tossIt(value){ // undefined value yields to false in boolean context
 7        value = value || ["head","tail"] //
 8        console.log(value);
 9    }
10    var mystery = ["black","white"];
11    tossIt(mystery); // passed arguments will be assigned
12    tossIt(); // default values will be provided
13    // what happens when number of parameters increased
14    function paintIt(baseCol,borderCol,northWalls,ceiling......){some code }
15    //calling function from somewhere in the program
16    paintIt(null,"offWhite","null","White")

But this approach gets more prone to errors when number of arguments increases for one basic reasons that human tends to forget what they had defined and in what order parameters are defined. Though for some it may not be an issue yet one solution is to assign default values to the parameters.

1    //providing default values when defining a function
2    function paint(baseColor,borderColor,northWall,ceiling ...){
3        baseColor = baseColor || "white";
4        borderColor = borderColor || "cream";
5        northWall = northWall || "skyBlue";
6        ceiling = ceiling || "white";
7    }
8
9    console.log(paint(baseColor,borderColor,northWall,ceiling));

But there exist an elegant approach to assign default values to the parameters using an Option object.The idea is that you define all your parameters as key value pair in an object and passed the object as an arguments. Passing an object has an advantage of getting updated if needs be without considering the order and number of parameters a function accepts.

 1//file-name : chap-01-17.js
 2function paintIt(options) {
 3  var baseColor = options.baseColor || 'white' //default values
 4  var borderColor = options.borderColor || 'cream'
 5  var northWall = options.northWall || 'skyBlue'
 6  var ceiling = options.white || 'white'
 7  //......
 8  console.log(
 9    'baseColor----> ' +
10      baseColor +
11      '\nborderColor----> ' +
12      borderColor +
13      '\nnorthWall----> ' +
14      northWall +
15      '\nceiling----> ' +
16      ceiling +
17      '\n'
18  )
19}
20//calling above function with only one variable
21// rest of the values will be set to default
22paintIt({ northWall: 'darkBlue' })
23//Creating an object to pass
24var optionsObject = {
25  baseColor: 'lightBlue',
26  borderColor: 'darkBlue',
27  northWall: 'null'
28}
29paintIt(optionsObject)
30// you can update one value depending upon any condition
31
32if (true) {
33  optionsObject.northWall = 'offWhite'
34}
35paintIt(optionsObject)
36console.log(optionsObject.northWall)

Accessing the extra arguments

So far we have established the fact that JavaScript does not throw an error if more arguments are passed than expected or even specifying any parameter list is not necessary, then how do those passed arguments are accessed within that function body. we will discuss this topic below .

Arguments are passed by reference or by values

If you are new to programming, you must understand that when a function is invoked with some arguments, those arguments can be passed either using their literal values or a variable referring to those values;

1fn(2) // number literal is passed
2fn('hello') // string literal is passed

if any variable is passed instead of the literal values, which refers to any primitive data type, it is not passed by the address ( which is also known as passing by reference ) but by value. What it means is that a copy of the value of that variable is made first before passing to the function. But it only applies to the primitive data type such as number and string and not to objects when passed as an argument of any invoking function.

1var x = 10
2function fn(value) {
3  console.log('Received value is :' + value) // 20
4  // change the value
5  value = 20 // Only local variable value  is changed
6  console.log('Value is changed :' + value) // 20
7}
8fn(x)
9console.log(x) // 10

In above code the value of variable x remains unchanged even though it was changed inside the calling function because its original address was not passed but a copy of the variable. If it was passed by reference the original value of the variable would be changed too.

How to access extra arguments passed to a functions

As we said earlier that a function can be passed more arguments than it is expected to receive, then how is possible to use those extra arguments in that function.To understand how it is done in JavaScript, first clear your mind that when a function is invoked ( called or executed ), it is given an array-like object named arguments. What it means is that whatever is passed to this function regardless of less or more arguments, can be accessed inside the function using this object acting as a local variable to this function. For example the first arguments passed to any function could be reached by using arguments[0], the second one by using arguments[1] and so on, thus the extra arguments can also be reached using this array-like object. Lets see this in the following example.

Note: Here the term array-like object is used instead of an array object the reason is that it is not an array object but behave like an array object to see more detail please visit mozilla.org

1function fn() {
2  for (var i = 0; i < arguments.length; i++) {
3    console.log('arguments are :' + arguments[i])
4  }
5}
6fn(1, 2, 3, 4)

The array-like object arguments is kind of a reference to the values passed as an argument. This means changing the one effects the other one. In other words while calling a function and passing same number of arguments as expected in the formal list of parameters in function definition then corresponding values are bound together thus they share the same values as seen below and can be changed interchangeably.

1function fn(value) {
2  console.log(value) // 5
3  console.log(arguments[0]) // 5
4  value = 10 // value is changed
5  console.log(arguments[0]) // 10 ,it gets changed too
6  arguments[0] = 100 // arguments[0] contents changed
7  console.log(value) // value is also changed
8}
9fn(5)

Binding b/w passing arguments and formal parameters

It is important to understand this process of binding otherwise it will mislead you easily. Thus keep in mind that if;

  • Equal number of arguments are passed then passing arguments and former parameters are bound together. Changing one of them will change the other.
  • If less number of arguments are passed than expected,then other parameters gets undefined value as a default JavaScript behaviour, and are not bound to the arguments object thus do not share the same value and updating one of them has no impact on the other and vice versa. This scenario is explained below.
 1function fn(x, y) {
 2  console.log('1. x is ' + x + ' y is ' + y) // 5 , undefined
 3  console.log('2. ' + arguments[0]) // 5
 4  console.log('3. ' + arguments[1]) // undefined
 5  // assigning new value to arguments[1]
 6  arguments[1] = 100
 7  console.log('4. ' + arguments[1]) // 100, gets updated
 8  console.log('5. ' + y) // still undefined
 9  //assigning new value to y
10  y = 50
11  console.log('6. ' + y) // 50
12  console.log('7. ' + arguments[1]) // 100, doesn't get updated
13}
14fn(5)

What happens to operations performed when less arguments are passed than expected

When less arguments are passed than expected, how an execution occurs depends what operation is being performed with the undefined parameters . The behaviour of an undefined variable depends upon the context it is used. For example when an undefined variable is added,subtracted to a number or multiplied , divided by a number its result is NaN. Similarly an undefined variable in boolean context will yield to false while with string objects it will converted to behave like another strings.

 1//file-name:chap-02-02.js
 2var x = 100,
 3  y = 200 //this x and y has no impact on fn()
 4function fn(x, y) {
 5  return x + y
 6}
 7console.log(fn(1, 8, 3, 4)) //9
 8console.log(fn(1, 8)) // 9
 9console.log(fn(1)) //NaN
10console.log(fn('hello :')) //hello  : undefined
11console.log(fn(true, '')) //true
12console.log(fn(undefined)) //NaN
13var a = [1, 3]
14console.log(fn(a)) //1,3 undefined

Higher-Order functions

This term has come from mathematics where it represents a function which accepts one or more functions as an arguments and can return a function as a result. These functions provides abstraction and solve problems in a way that looks more simplistic than done otherwise.

First-Order functions

This term is used for other functions which are not higher order function. They may or many not accept a value and can return some value. They are used to share functionality time and time again.

Closures

The concept of closures is to do with scope and rules has changed since ECMAScript 6. This section will describe JavaScript behaviour before this specification. Scope is about where a declared variable or a function can be accessed from . A variable declared within a function is not accessible outside the function and it is called to have local scope or function scope. But if we have nested functions i.e., function inside the function then what happens. Here we are dealing with scope chain, nested functions can have access to its own variables plus access to outer function variables in which they are defined further more they can have access to global variable. But it is not all, the power of closures comes from having an access to the parent scope, even when the function has closed. What it means is that if your nested function is returned or it returns some object. Then this object has still access to the local variable of the parent function.

Returning an anonymous function

 1function makeWords() {
 2  var prefix = ['un', 'de', 'in', 'il', 'im']
 3  return function (word) {
 4    var pre = prefix.pop()
 5    console.log(pre + word)
 6  }
 7}
 8var getPrefix = makeWords()
 9getPrefix('proper') //improper
10getPrefix('legal') //illegal
11getPrefix('complete') //incomplete
12getPrefix('rail') //derail
13getPrefix('known') //unknown
14getPrefix('')

In above code the nested function have access to local variable of enclosing function. This access is provided a link between the nested function and its environment where it is created. This unbroken link with its parent function ( enclosing function ) exist even when the execution comes out the enclosing function. In above scenario this is achieved either by returning an anonymous function or an object that defines that function or a reference to a function which can be used by the reverencing variable.Another version of the same code could be written as follows.

Returning an object

 1function makeWords() {
 2  var prefix = ['un', 'de', 'in', 'il', 'im']
 3  return {
 4    nextWord: function (word) {
 5      var pre = prefix.pop()
 6      console.log(pre + word)
 7    }
 8  }
 9}
10var getPrefix = makeWords()
11getPrefix.nextWord('proper')
12getPrefix.nextWord('legal')
13getPrefix.nextWord('complete')
14getPrefix.nextWord('rail')
15getPrefix.nextWord('known')
16getPrefix.nextWord('')

Returning a reference to nested function

 1function makeWords() {
 2  var prefix = ['un', 'de', 'in', 'il', 'im']
 3  var nextWord = function (word) {
 4    var pre = prefix.pop()
 5    console.log(pre + word)
 6  }
 7  return nextWord
 8}
 9var newWord = makeWords()
10newWord('proper')
11newWord('legal')
12newWord('complete')
13newWord('rail')
14newWord('known')
15newWord('')

it is the variable that receives the returned nested function said to become the closure because it has access to local variable of a function which has exited.

Adding properties to your function

Since functions are also objects the properties can also be added to function but if you just want to add properties to your function because it is an object. Then add it to object directly because this is one of the reasons objects are present and designed. The job of function is to provide you the service to do some job time and time again and not to force it act like an object hence there will be no use of forcing function to behave like objects even though they are internally implemented as objects.

Despite, there are certain times when adding properties to a function makes sense to achieve the purpose. Before embarking how to do it, make this thing clear that the issue here is to add properties to function and use them accordingly. A function can be named or un named does not change the issue here. Let’s see how it is done.

 1var guest = function (name) {
 2  guest.counter = 0
 3  guest.sirName = name
 4  return name === undefined ? guest.counter : ++guest.counter
 5}
 6// Before invoking the function
 7console.log('//----Before Invoking the function-----//')
 8console.log('guest.sirName = ' + guest.sirName) // undefined
 9console.log('guest.counter = ' + guest.counter) // undefined
10
11console.log('//----Invoking function-----//')
12console.log('guest() : ' + guest()) // guest() : 0
13
14console.log('//----After Invoking the function-----//')
15console.log('guest.sirName : ' + guest.sirName) // undefined
16console.log('guest.counter = ' + guest.counter) // 0

Number of points to note here:

  1. To assign the values assignment operator = is used instead of usual one : because it is function body block not an object code block.
  2. Since it is not a constructor function no this keyword is used with variables instead the function name.

There will be no error but at the same time there will be no output from this function. This function does exist as other normal function but values inside the functions are not assigned any data.

  1. To assign the value inside the function it needs to be invoked first. Once it is invoked this function performs correctly. To avoid calling it explicitly this function can be made a self executable function making it ready to be used.
1var guest = (function (name) {
2  guest.counter = 0
3  guest.sirName = name
4  return name === undefined ? guest.counter : ++guest.counter
5})()

The above code would not compile because of using " : " operator to assign values within a function, even if you use " = " operator it wont work. First of all command refers to a function and to invoke the function you need trailing brackets (). Secondly accessing the property using dot notation (.) is allowed with instance of an object. In the above case there is no instance of an object. This topic of using functions as an object leads to the topic of constructor functions where the properties are defined using this key word so that an instance invoking the function can access them.

1function Animal() {
2  this.name = 'any name'
3}
4//
5var monkey = new Animal()
6console.log(monkey.name)

Function Scope

-If a function does not return a value and it is assigned to a any variable that variable value and type both are undefined as var what = doNothing();To see the value of a variable use console.log() function and to find out the type of this variable use built in function typeof().

1var what = doNothing();
2console.log("The value of variable what is " + what "\n The type of what is " + typeof(what));

If a function does return a value and it is assigned to a variable that variable type becomes the same type of the returned item.The value of the returned item ( variable , object or a function ) is assigned to that receiving variable.

Functions are values

When a variable is declared and assigned a value the assignment operator = executes the statement and puts that value into the variable. In other words the memory reserved by the variable declaration now holds the assigned value. Similarly that value does not have to be any number or string it can be a function itself thus it is said , in JavaScript functions are values too.

 1//First declaring a function , it can be used as a value
 2function message(contents) {
 3  console.log('your message:' + contents)
 4}
 5//note  a function is being assigned to a variable as a value
 6
 7var firstMessage = message // no  parenthesis()
 8
 9//invoking a function not by its name but by a variable that has been
10//assigned this function. To invoke " ( ) " are necessary if invoked
11//without  " ( ) " it represent the whole function.
12
13firstMessage("\'your are free to go\'") // Note arguments are pass to a variable just as it was an original

Calling a function inside the same function

A function in turn can invoke itself inside its own body this would be regarded as recursion. It needs to be handled carefully.

 1var result;
 2var makeItTen = function addOne(value){
 3    if ( value < 10){
 4        console.log("value is = " + value);
 5        result = addOne(++value); <------------ calling itself
 6        console.log("just gone back one step when value was " + value);
 7        }else{
 8            console.log("Returning  when value is " + value);
 9            return value; <--------- this return is assigned to variable "result"
10        }
11return result; <--------- this returns the computed value to the initial callee
12};
13console.log("The Final value is : " + makeItTen(0));

A Recursion example

The above can be written in much simpler and elegant way calling return recursively.

1var makeItTen = function (value) {
2  if (value < 10) {
3    console.log('The value is : ' + value)
4    return makeItTen(++value)
5  } else {
6    return value
7  }
8}
9console.log('Final value is : ' + makeItTen(0))

The same result can be achieved without using any recursion at all by means of loops.

1var makeItTen = function (value) {
2  for (; value < 10; value++) {}
3  return value
4}
5console.log('Final value is : ' + makeItTen(0))

Notes: When performing recursion it is not easy to track the flow of code mentally. Thus it should be used when it is really necessary and make sense. Look at the following program and guess what value is returned to the initial callee.

 1var makeItTen = function (value) {
 2  if (value < 10) {
 3    console.log('The value is : ' + value++)
 4    makeItTen(value)
 5  } else {
 6    return value
 7  } //                           |------Calling a function
 8}
 9V
10console.log('Final value is:' + makeItTen(0))

Using arguments.callee to call itself

JavaScript also provides a way to call itself , following example uses this option.

1function makeItTen(value) {
2  if (value >= 10) return value
3  console.log('The value is : ' + value)
4  return arguments.callee(++value)
5}
6console.log('Final value is : ' + makeItTen(0))

Though the above use of callee does not impose any problem but it is not necessary the name of callee function can be used to call itself. The appropriate use of arguments.callee would be within an anonymous function.

Note: arguments.callee is deprecated in ECMAScript 5 Strict mode because of problems with tail recursion.

NameSpace

When writing your programme in JavaScript it is best not to expose your variables and functions globally. To hide them from a global context there is no way present in language. However programmers have designed the style of coding which has become the idioms of JavaScirpt and commonly used among the developers. To achieve this purpose one of the technique used is to make use of IIFE ( Immediately Invoked Function Expression). Thus everything is wrapped around the function which is itself wrapped with curly brackets making the function to become the un available either to host environment or to other code at the same time making it a module which can be used everywhere without fearing of global Namespace conflicts.

What makes a language a Functional Programming Language

  • The ability to pass a function as an arguments to other function
  • The ability to define a function as an argument when invoking a function
  • The ability to infer the type if necessary
  • The ability to provide the best use of anonymous function
  • The ability to use them as high order function

Next Steps

Deepen your understanding of JavaScript functions and functional programming with top-rated JavaScript courses on Udemy — covering closures, higher-order functions, and advanced patterns.