JavaScript Functions

The functions have an internal property names [[Call]]. This property is unique to functions and indicate that the object can be executed. Just because of this property the typeof operator returns type as “function”. In the past different browsers were identifying multiple reference types, for example regular expression, as function that has been corrected now.

Functions can be declared in two different forms;

The first form is function declaration where the function has a name;

function add(num1, num2){
return num1 + num2;
}

The second form is function expression where the function has no name;

var add = function(num1, num2){
return num1 + num2;
};

This code actually assigns a function value to the variable add. The function expression is almost identical to function declaration except for the missing name and the semicolon at the end.

These two forms are similar but there is a difference. Function declarations are hoisted to the top of the context when the code executes. This code might look like it will cause an error, but it works;

var result = add(5,5);		//return 10
function add(num1, num2){
return num1 + num2;
}

The reason, JavaScript engine hoists the function declaration to the top and actually executes the code as if it were written like this;

function add(num1, num2){
return num1 + num2;
}
var result = add(5,5);		//return 10

Function hoisting happens only for function declaration because function name is known ahead of time. This is not true for function expressions.

var result = add(5,5);		//return error
var add = function(num1, num2){
return num1 + num2;
};

If we always define functions before using it, both approaches will work.

Passing Parameters

JavaScript functions allows you to pass any number of parameters to a function without causing any error. The reason, function parameters are stored an array-like structure called arguments. Arguments are similar to JavaScript array. The arguments values are referenced via numeric indices and there is a length property to determine how many values are present.

The argument object is automatically available inside any function. This means names parameters in a function exists mostly for convenience and don’t exactly limit the number of arguments that a function can accept. Function won’t throw an error if we pass too many or too few parameters.

Here is an example;

function reflect(value) {
return value;
}
console.log("hi");		//returns “hi”
console.log("hi", "there");	//returns “hi there”
reflect.length			//returns 0

The same function can be written as;

reflect = function(){
return argument[0];
};
console.og("hi", "there");	//returns “hi”
console.log("hi", "there");	//returns “hi there”
console.log(reflect.length)	//returns 0

The first implementation is much easier to understand because of named argument. The second implementation is using arguments and we much read the body to understand how arguments are used.

The best practice is to use named argument. However, using arguments is actually more effective in case we want to create a function that accepts any number of parameters and return their sum.

function sum()
{
    var result = 0;
    i = 0;
    len = arguments.length;
    
    while (i < len) {
        result += arguments[i];
        i++;
    }
    return result;
}

console.log(sum(1,2)); 			//returns 3
console.log(sum(1,2,3,4,5));		//returns 15
console.log(sum(1,2,3,4,5, 6, 7 , 8));	//returns 36
console.log(sum());			//returns 0
console.log(sum(50));			//returns 50

Function overloading

There is no concept of function overloading in JavaScript. JavaScript function can accept any number of parameters.

function sayMessage(message) {
    console.log(message);
}

Overloading this function;

function sayMessage() {
    console.log("Default message");
}
sayMessage(“Hello”)			//returns “Default message”

Why do we see “Default message” where it should be “Hello”. When we define multiple functions with the same name, the one that appear last in code wins.

We can mimic overloading functionality using this approach;

function sayMessage(message) {
    if (arguments.length == 0) {
    	console.log("Default message");
    }
console.log(message);
}
sayMessage("hi")		//returns “hi”
sayMessage()			//returns “Default message”

Object Methods

Properties can be added or removed from objects at any time. When a property value is function, it’s considered a method.

var person = {
    name:"Shahzad",
    sayName: function(){
        console.log(person.name);
    }
};
person.sayName()		//returns “Shahzad”

Syntax for data property and method is exactly the same. An identifier followed by : and the value. For function the value would be function().

The “this” Object

In our previous example, sayName() method reference person.name directly, which creates tight coupling between the method and the object. If we change the variable name, we also need to remember to change the reference to that name in method. Second, it would be difficult to use the same function for different objects.

Every scope in JavaScript has a “this” object that represents the calling object for the function. In the global scope, this represents the global object (window in web browsers). When a function is called while attached to an object, the value of “this” is equal to that object by default.

Let’s re-write the code;

var person = {
    name:"Shahzad",
    sayName: function(){
        console.log(this.name);
    }
};
person.sayName()		//returns “Shahzad”

This code works the same as the earlier version, but this time, sayName() references “this” instead of person.

Let’s go with another example. Create a function “sayName”. Create two object literals and assign sayName to the sayNameFor function. Functions are reference values so they can be assign as property values on any number of objects.

Define a global variable called name. When sayNameForAll() is called directly, it will output global variable value.

function sayNameForAll() {
    console.log(this.name);
}

var person1 = {
    name: "Shahzad",
    sayName: sayNameForAll
};

var person2 = {
    name: "Ali",
    sayName: sayNameForAll
};

person1.sayName()		//returns “Shahzad“
person2.sayName()		//returns “Ali”
sayNameForAll();		//returns empty value

Why sayNameForAll() returns null because there is no global scope variable. Let’s define one;

var name = “Hamza”;
sayNameForAll();		//returns “Hamza”

Changing this

The ability to use and manipulate the “this” value of functions is key to good object-oriented programming in JavaScript. There are three function method that allow us to change the value of this. Functions are objects and objects have methods, so function can, too.

The call() Method

This execute the function with a particular this value and with specific parameters. Let’s take our earlier example;

function sayNameForAll(label) {
    console.log(label + ":" + this.name);
}

var person1 = {
    name: "Shahzad"    
};

var person2 = {
    name: "Ali"
};

var name = “hamza”;

sayNameForAll.call(this, "global");		//returns global:hamza
sayNameForAll.call(person1, "person1");	//returns person1:Shahzad
sayNameForAll.call(person2, "person2");	//returns person2:Ali

sayNameForAll() accepts one parameter that is used as a label to the output value. There are no parentheses after the function name because it is accessed as an object rather than as code to execute. We did not added the function directly on each object. We explicitly specify the value of this instead of letting the JavaScript engine do it automatically.

The apply() Method

The second method we can use to manipulate “this” is apply(). This method works exactly the same as call() except that it accepts only two parameters: the value for this and an array or array-like object of parameters (it means we can use an arguments object as the second parameter). We can call our methods like this;

sayNameForAll.apply(this,["global"]);		//return global:hamza
sayNameForAll.apply(person1,["person1"]);	//return person1:Shahzad
sayNameForAll.apply(person2,["person2"]);	//return person2:Ali

The use case between call and apply; if we have an array of data, we will use apply(). If we just have individual variable, we will use call().

The bind() Method

This method was added in ECMAScript 5 and it behaves quite differently than the other two. The first argument to bind() is the “this” value for the new function. All other arguments represent named parameters that should be permanently set in the new function.

We can call our methods like this;

var sayNameForPerson1 = sayNameForAll.bind(person1);
sayNameForPerson1("person1");	//returns “person1:Shahzad”

var sayNameForPerson2 = sayNameForAll.bind(person2);	
sayNameForPerson2("person2");	//return “person2:Ali”

Resources

6 Ways to Declare javaScript Function

JavaScript Default Parameters

JavaScript Reference types

Reference types represent objects in JavaScript. They are the closet things to classes. Reference values are instances of reference types.

An object is an unordered list of properties consisting of a name (always a string) and a value. When the value of a property is function, it is called a method.

It helps to think of JavaScript objects as nothing more than hash tables;

—–object——-

|name|value|

|name|value|

Objects can be created using the new operator with a constructor. A constructor is simply a function uses new to create an object. By convention, constructors in JavaScript begin with a capital letter to distinguish them from non-constructor functions. For example;

var object = new Object();

Reference types don’t store the object directly into the variable. It holds a pointer to the location in memory where the object exists. This is the primary difference between objects and primitive values. When you assign one variable to another, each variable gets a copy of the pointer and both reference the same object in memory.

var object = new Object();
var object1 = object;

—-Variable Object—-                                   Memory

|object|——|————->                Pointer1

|object1|—-|————–>                Pointer1

JavaScript is a garbage-collected language, so we don’t need to worry about memory allocations when using reference types. However, the best practice is to deference objects that are no longer required so that garbage collector can free up that memory. The best way to do so;

var object1 = new Object();
//do something
object1 = null;		//dereference

You can add or remove properties from objects; for example;

var object = new Object();
var object1 = object;
object.customProperty = “Awesome!”;
console.log(object1.customProperty);	//returns “Awesome”

The property that’s added to object variable is accessible on object1. The reason, same pointer.

Object type is one of a handful built-in reference types that JavaScript provides. The other builtin types are;

Array =  An ordered list of numerically indexed values

Date = A date and time

Error = A runtime error

Function = A function

Object = A generic object

RegExp = A regular expression

Each of these built-in reference types can be instantiated using new;

var items = new Array()
var now = new Date()
var error = new Error("something bad happend")
var func = new Function("console.log('hi');")
var object = new Object();
var re = new RegExp("\\d+");

Several built-in reference types have literal forms. A literal is a syntax that allow us to define a reference value without explicitly creating an object, using the new keyword.

Object literal

To create an object, we define the properties of new object inside braces. For example;

var book = {
name: "My favorite book",
year: 2014
};

Another format for creating the object if there are spaces in properties;

var book = {
"name": "My favorite book",
"publish year": 2014
};

When using object literal, the JavaScript engine implicitly creates a new Object(). This is true for all reference literals.

Array literal

Array literal can be defined in a similar way;

var colors = ["red","green","blue"]
console.log(colors[0])

This code is equivalent to the following;

var colors = new Array("red","green","blue")
console.log(colors[0])

Function literal

The best approach is to define functions using their literal form. Creating functions is much easier and less error prone using this literal form;

function reflect(value) {
return value;
}

We can create same function using function constructor;

var reflect = new Function("value", "return value;");

Using function constructor is typically discouraged given the challenges of maintaining, reading and debugging a string of code rather than actual code. There is no good way to debug these functions because these are not recognized by JavaScript debuggers. They are like a black box in your application.

Regular Expression literals

Regular expression literal form is;

var numbers = /\d+ /g;

Constructor equivalent is;

var numbers = new RegExp(“\\d+”, “g”);

When using RegExp constructor, patterns are passed as string. Any back-slashes need to be escaped. That’s why \d is used in literal and \\d is used in the constructor above.

Regular expression literals are preferred over the constructor form except when regular expression is being constructed dynamically from one or more strings.

Functions as an exception, there is no right or wrong way to instantiate built-in types.

Property Access

Properties are name/value pairs that are stored on an object. Properties can be accessed by dot notation or bracket notation with a string;

with dot notation;

var array = [];
array.push(12345);

with bracket notation the name of the method is enclosed in square brackets;

var array = [];
array["push"](12345)

This syntax is useful when we want to dynamically decide which property to access. For example, bracket notation allows us to use a variable instead of the string literal to specify the property to access;

var array = [];
var method = "push";
array[method](12345)

bracket notation allows you to use special characters in the property names. dot notation is easier to read and can be seen more frequently in applications.

How to identify reference types

The easiest reference type to identify is function type. Typeof operator on a function should return its type “function”.

function reflect(value) {
return value;
}
console.log(typeof reflect);		//returns “function”

On all other reference types, typeof operator returns “object”. This is not helpful. To solve this, there is another JavaScript operator, instanceof. This operator takes an object and a constructor as parameters. When the value is an instance of the type that constructor specifies, instanceof return true; otherwise, returns false.

var items = [];
var object = {}
function reflect(value) {
return value;
}
console.log(items instanceof Array);		//true
console.log(object instanceof Object);		//true
console.log(reflect instanceof Function);		//true

Every object is actually an instance of an Object because every reference type inherits from Object. The instanceof operator can identify inherited types.

console.log(items instanceof Array);		//true
console.log(items instanceof Object);		//true
console.log(object instanceof Object);		//true
console.log(object instanceof Array);		//false
console.log(reflect instanceof Function);		//true
console.log(reflect instanceof Object);		//true

How to Identify Arrays (Special Case)

Instanceof operator can identify arrays. There is an exception though. JavaScript values are passed back and forth between frames in the same web page. Each web page has its own global context i.e. its own version of Object, Array and all other built-in types. As a result, when we pass an array from one frame to another, instanceof doesn’t work because the array is actually an instance of Array from a different frame.

ECMAScript 5 introduced Array.isArray() that solves this problem.It identifies the value as an instance of Array regardless of the value’s origin.

var items = [];
console.log(Array.isArray(items));	//returns true

The Array.isArray() method is supported in most browser and in Node.js. This method doesn’t support IE 8 and earlier.

JavaScript Primitive (value) types

There are five primitive types; Number, String, Boolean, null and undefined. Their values are stored directly in the variable for a given context. We can use typeof operator to identify primitive types with exception of null, which must be compared directly against the special value null.

color1 = "red"
color2 = color1
color2 = "green"
Inspect type of variables;
typeof(color1)		//string
typeof(color2)		//string
typeof(10)		//number
typeof(true)		//Boolean
typeof(undefined)	//undefined

This is tricky value type.

typeof(null)		//object

This has been acknowledge by TC39 as an error, the committee that design and maintain JavaScript.

The best way to determine if a value is null is to compare it against null directly;

value = null
value === null	//true
value = false	//false
value === null
“10” == 10	//true
“10” === 10	//false

When you use the double equals, the string “10” and the number 10 are considered equal because the double equals converts the string into a number before it makes the comparison. The triple equals operator doesn’t consider these values equal because they are two different types.

console.log(undefined == null)		//true
console.log(undefined === null)		//false

Null is a data type that has a single value null. When you’re trying to identify null, use triple equals so that you can correctly identify the type.

Strings, numbers and Booleans primitive types have methods. The null and undefined types have no methods. Strings, in particular have numerous methods.

var name = "Shahzad Khan"
var lowerName = name.toLowerCase()	//convert to lowercase
var firstLetter = name.charAt(0)		////get first character
var middleOfName = name.substring(2,5)	//get character 2-4
s.length		//return number of characters
var count  =10
var fixedCount = count.toFixed(2)	//convert to “10.0”
var hexCount = count.toString(16)	//convert to “a”
var flag = true;
var stringFlag = flag.toString()		//convert to “true”

Primitive values are not objects though they have methods.

“Not a number” is used in cases where an arithmetic operation produces a result that is not a number.

a = 9/undefined		//display NaN
typeof a			//display number

Equality operator (>, <, ==, !=, >=, <=) return Boolean as their result.

var f = 10
var t = 20
f != t		//return true

The undefined data type is returned when we access a property on an object that does not exists or use it before it is declared or before it is assigned a value;

typeof(z)		//variable is not declared

There are some values in these types which evaluates to true and some evalues to false;

false, 0 (zero), “” (empty string), null, undefined, NaN (technically NaN is not true/false. It can only be detected with isNaN function)

To test this;

0 == false

All other values represent true values.

When evaluating the value of variables in conditional statement we do this;

var a = null
if (a == undefined || a == null)
{ a = 1;
}

It is possible to simple write

var a = null
if (!a) {
a = 10
}

Likewise, if a variable has a value, we can write something like;

If (a){
console.log(a)
}

This shortcut is useful and extensively used in JavaScript code.

JavaScript is a dynamically typed language. In a statically typed language, the compiler can perform type checking, if a variable is defined to store an integer. JavaScript variables derive their types based on the values they are assigned at run-time. Variables can change their type if they are assigned a new value.

As a result, it is not possible to perform static type checking in JavaScript.

Consider this example;

function add(v1, v2) { 
return v1 + v2 
}

If we invoke this function as;

add(1,1)		//return 2

This is expected result. We can also invoke this function as;

add("1",1)		//return 11

This is unexpected because JavaScript has performed string concatenation between number and the string. This is one of the reasons why the typeof operator is so important. It allows the function to be rewritten as;

function add(v1, v2) {
    if (typeof v1 === "number" && typeof v2 === "number") {
    return v1 + v2;
} else {
    throw "both argumens must be number";
    }
}

Now try to pass arguments;

add(“1”,1)		//return “both arguments must be number

On a side note, using the “+” operator on different data types produces a variety of random results;

{} + []		//return 0
[] + {}		//return object
Even using the “+” operator on the same data types produce meaningless results;
[] + [] 		//return empty string
{} + {}		//return object array