Functions

Basics, anonymous functions, constructor, predicates

Santosh Rajan
Functional JavaScript
6 min readMar 25, 2014

--

Functions are the basic unit of code reuse in JavaScript. Functions are also about much more than just code reuse as we will see in this chapter. This chapter will build the readers capabilities in order to understand the subsequent chapters. We will discuss the concepts and functions that will be used in subsequent chapters.

alert(“Hello John”)
alert(“Hello Bill”)

You can type the two lines above into a browser console. The lines will alert “Hello John” and “Hello Bill”. If you noticed the console also printed undefined on the console, because that is what the alert function returns. We are repeating the same code in each line. We can reuse this code by abstracting it away in a function.

function greet(name) {
alert(“Hello “ + name)
}

Now we can use the greet function without needing to know how it works. We just call it with a name. In other words we have abstracted away the code into a function.

Function greet will return undefined. That is because we did not explicitly return anything. In JavaScript if a function does not explicitly call return with a value, the function returns undefined.

function greet(greeting, name) {
alert(greeting + “ “ + name)
return “Greeting sent to “ + name
}
greet(“Hello”, “John”)
greet(“Welcome”, “Jim”)

We now do some more abstraction. The function takes a greeting message also, and we return a value too.

Function arguments

JavaScript allows you to define a function without specifying its arguments. And you can access the arguments within the function using the arguments value. arguments is an array like object, but not an array. It has the length property, but does not have access to other array methods like push, pop, slice etc.

Here we rewrite the greet function to take any number of names.

function greet() {
for (var i = 0; i < arguments.length; i++) {
alert(arguments[i])
}
}
greet(“John”, “Jim”, “James”)

In the function above we treated the arguments object as an array by accessing its length property, and each element using the array subscript.

Function length

Each function has a length property which is the number of arguments specified in its definition.

function add(x, y) {
return x + y
}
add.length //==>> 2
function add() {
return arguments[0] + arguments[1]
}
add.length //==>> 0
add(2, 4) //==>> 6

In the second example we did not specify arguments in the function definition, hence its length was 0. But our add function worked just fine because we accessed the arguments by subscripting the arguments object.

Function call method

Each function has a call method attached to it. You can use the call method to change the context in which the method is called. eg. Arrays have a slice method.

[1, 2, 3].slice(1) //==>> [2, 3]

What is interesting is that we can change the context in which slice is called and use it to convert an array like object to a proper array. In the example below we convert the arguments object into an array by calling

[].slice.call(arguments)

The first argument to call is the context, and the rest of the arguments are the arguments you pass to slice. In this case we don’t pass any arguments to slice because we want the whole array back. The above is same as calling

Array.prototype.slice.call(arguments)

Converting arguments and other array like objects to arrays is a common pattern you will encounter in JavaScript. We can abstract that pattern away into a function.

function toArray(args) {
return Array.prototype.slice.call(args)
}

We use the Array.slice method to convert the array like object into an array. The slice method returns a new array, and does not check if the passed object is actually an array. It just checks the length, and accesses the elements using the subscript, not unlike what we did in our example.

Function apply method

The functions apply method works just like call above, with the difference being that it takes an array like object as its second argument, which will be used as the arguments to the function.

The function bind takes a function and a context as it arguments and returns a new function that binds the given function to the new function.

function bind(fn, context) {
return function() {
return fn.apply(context, arguments)
}
}

The bind operation returns a new function. When the new function is called with a set of arguments, the bound function’s apply method is called with the context and arguments. In ecmascript 5 the bind method is available to all functions, so we don’t need to use the bind function above.

Anonymous functions

In the bind function example above the new function returned was an anonymous function. Anonymous functions are function expressions, so they can not appear on the left hand side of a statement. They can be used on the right hand side of a statement (like in the return statement above) or passed as arguments to a function. You can assign them to variables.

var greet = function(name) {
alert(“Hello “ + name)
}

In the example above we rewrite the greet function from earlier in this chapter. Here we assign an anonymous function to a variable named greet. The former function definition was a function declaration, while the latter is a function expression.

Both forms of the function definition will work for you. However there is a difference of note. Function declarations are evaluated at compile time, and you can call the function even before the definition.

greet(“John”)
function greet(name) {
alert(“Hello “ + name)
}

We call greet before it is defined in the example above. And this will work.

greet(“John”)
var greet = function(name) {
alert(“Hello “ + name)
}

The example above will not work, and will throw an error. This is because the function expression is evaluated at runtime, because of the assignment statement.

Function constructor

Another way to create a function is to create a new object of the Function class.

var greet = new Function(“greeting”, “name”, ‘alert(greeting + “ “ + name)’)
greet(“welcome”, “John”)

The Function constructor takes a set of argument name strings, which will be used as the argument names for the created function. The last argument is a string containing all the code within the new function. The new statement is not required. The following will also work.

var greet = Function(
“greeting”, “name”, ‘alert(greeting + “ “ + name)’)
greet(“welcome”, “John”)

The function created by the function constructor will execute in the global scope. So the following code will not work. It will throw an error.

var a = 1
var add1 = new Function(“b”, “return a + b”)
add1(2) //==>> ReferenceError: a is not defined

So it is important to remember here that functions created using the function constructor are not closures, unlike the other two ways we created functions. More on closures later.

Predicate Functions

A function that returns a boolean true or false is known as a predicate function. They are very useful in programming languages, for type checking, truth checking etc. It is always useful to have a set of predicate functions at hand and we will write some here.

function isNumber(obj) {
return Object.prototype.toString.call(obj) ===
“[object Number]”
}

Every object has a toString method which is inherited from the generic Object. The method may be overridden by subclasses of Object. However we can call the the generic objects toString method via its prototype, and change the context to our own object via the its call method, yielding a string like [object type].

That is what we do in the above function. However the call to Object.prototype.toString is so commonly used that we can write a function for it.

function getType(obj) {
var type_str = Object.prototype.toString.call(obj)
var type_arr = type_str.match(/.* (.*)\]/)
return type_arr[1]
}

First we get the type string of the passed object. Next we match it with a regular expression to extract the type part so we get a string like Number, Array etc. The required part will be the second element of the matched array which we return. We can write the whole thing in one line like below.

function getType(obj) {
return Object.prototype.toString.call(obj)
.match(/.* (.*)\]/)[1]
}
getType(10) //==>> Number
getType(“”) //==>> String
getType([]) //==>> Array
getType({}) //==>> Object
getType(null) //==>> Null
getType(undefined) //==>> Undefined
getType(true) //==>> Boolean
getType(getType) //==>> Function
getType(new Date()) //==>> Date

So we can write isNumber as

function isNumber(obj) {
return getType(obj) === ‘Number’ && !isNaN(obj)
}

Note that we had to add one more condition. That is because in JavaScript NaN will also show type Number! And we need to guard against that. In some cases getType is not the most efficient operation. We can use typeof and Array.isArray in some cases.

So we now can write all the type predicates as below.

function isNumber(obj) {
return typeof obj === ‘number’ && !isNaN(obj)
}
function isString(obj) {
return typeof obj === ‘string’
}
function isArray(obj) {
return Array.isArray(obj)
}
function isObject(obj) {
return getType(obj) === ‘Object’
}
function isNull(obj) {
return getType(obj) === ‘Null’
}
function isUndefined(obj) {
return getType(obj) === ‘Undefined’
}
function isFunction(obj) {
return getType(obj) === ‘Function’
}
function isDate(obj) {
return getType(obj) === ‘Date’
}

Another useful predicate is isEmpty.

function isEmpty(obj) {
if (obj === null || obj === “”) return true
if (isArray(obj) && obj.length === 0) return true
if (isObject(obj) && Object.keys(obj).length === 0) return true
return false
}

--

--

Santosh Rajan
Functional JavaScript

Founder www.geekskool.com. Programmer for over 30 years. Making better programmers is my passion. Bangalore. India. www.santoshrajan.com