Just JavaScript - How Functions Become Methods
Written by Ian Elliot   
Thursday, 15 May 2014
Article Index
Just JavaScript - How Functions Become Methods
Function Objects Are Late Bound
The JavaScript Difference

In this part of our radical exploration of JavaScript the topic is how a Function object becomes a method with the help of "this" - perhaps the most maligned of JavaScript keywords. We also look at how to early and late bind methods. 

Just JavaScript 
A Radical Look At JavaScript

  1. In The Beginning Was The Object
  2. The Function Object 
  3. How Functions Become Methods
  4. The Object Expression
  5. Object Construction

JustJavaScripticonSo far we have looked at the role that the Function object plays in bringing executable code to JavaScript in general. Other languages have functions, methods or subroutines but JavaScript has the Function object which is a general object which has an additional default "code" property that can be evaluated using the evaluation or invocation operator (). 

In this chapter the aim is to show how Function objects are used as methods by other JavaScript objects. Key in this transformation is the "this" keyword.

Objects with function properties

As we discovered in Chapter 1, an object is a set of properties with object values. As a function is nothing more than a Function object there is no reason why a function cannot be a property of another object.

For example:

var myObject={myFunction:
        function(){alert("My Function");}};

creates a new object with a single property myFunction which is a Function object with code body:

alert("My Function");

The only problem with defining Function properties is how to format them on the page to make the code clear. Most use something like:

var myObject={
    myFunction: function(){
       alert("My Function");
    }
};

 

To execute the code body of the Function property you simply need a reference to the Function object i.e.

myObject.myFunction

and the evocation operator () which gives:

myObject.myFunction();

And it is always worth remembering the difference between the two.

If there were parameters they would be included in the usual way between the brackets. 

You can also write:

myObject["myFunction"];

as the reference to the Function object and

myObject["myFunction"]();

as the evaluation of the function body. In this form it looks a lot less like a traditional function call but there is nothing new here either.

Why would you use an object with Function properties?

Namespaces

An object is a good was to gather together functions that do the same sort of job. For example the built in Math object provides a place to group mathematical functions like sin, cos and so on. To use such a function you have to write something like:

var ans=Math.sin(0.5);

In this case it might seem inconvenient to have to write the full "dotted" reference to the Function object but in general it is useful to be able to separate the name applied to this function and any other function which might happen to have the same name. 

In other words using Functions within objects is a way of avoiding name collisions. 

When ever you are working on a large program trying to find unique names for things becomes increasingly difficult as the program gets bigger. You generally end up applying a good name to the first function or variable of a particular type such as totalHours only later to have to use something less meaningful such as tHours to avoid the name collision with the first function or variable. 

In other languages name collisions are made less of a problem by they use of "namespaces" which assign multipart names for things without having to get involved in creating objects necessarily. Usually the first part of the name is derived by the IDE or the language conventions unless there is a name collision when you have to provide a fully qualified name. 

Object are often used in JavaScript at namespaces just like the Math object. If you want to create an alternative function called sin then you can because the built-in sin's full name is Math.sin. 

Of course to avoid a name collision with someone else's sin function you would be well advised to put your new function within a suitable object - e.g. myMathFunctions. Of course the trick here is finding a name for your "namespace" object that is going to be unique and so avoid an initial name collision.  This is the reason why some programs make use of a domain name for the object e.g. iprogrammerinfo but this is usually necessary and makes things look complicated. 

You can also make use of multiple nested object to create a nested namespace. So you could have

myMath.trig.sin

or

myMath.optimize.linear

and so on. 

JavaScript doesn't have explicit support for namespaces and so using objects as namespaces makes good sense. 

You can even simplify naming where required by assigning the fully qualified name to something shorter. For example:

var sin=Math.sin;

and following this statement you can just write 

var result=sin(0.5);

To labour the point for one final time notice that Math.sin isn't a function it is a reference to a Function object that is one of the properties of the Math object. 

Functions become methods

You might at this point be thinking that we have just looked at how an object can have methods - this isn't so. 

An object can have Functions as properties and this is useful but a simple Function object even when assigned as a property isn't a method.

Why not?

The reason is that a method is something that an object does to itself. That is the code of a method doesn't just do something external like compute a sin or a square root. A method is something that you ask an object to do like print itself or use its data properties to make a connection to a secure server or copy itself. 

A method is an action that an object performs which involves other parts of the object.

Yes the definition is vague and you could argue that a collection of math functions were methods but the best test of whether a function is a method is to ask if it would work in the same way if you removed it from its object. That is Math.sin(0.5) can be considered to work in the same way and do the same job as sin(0.5).

Now consider a something like:

myObject.size();

which returns the size of the object computed in some way appropriate to the object. Ask yourself what does:

size();

mean when it is removed from the object? Clearly by our definition size() is a method as it needs to know the object it is a property of to do its job. 

At this point you may object slightly and point out that you can convert size the method into size the function by providing it with a parameter. That is

myObject.size();

is the same as:

size(myObject);

both of which return the size of the object in some appropriate way.  

Yes absolutely right and it's not really an objection.

This swapping of object property to parameter is the key to the difference between a method and a pure function.

For a function to be a method it has to accept the object it belongs to as some sort of default parameter - and this is where "this" comes in. 

The Problem

Consider for a moment a simple example of a function as an object property:

var myObject = { mySize: 99,
                 getSize: function() {
                   return mySize;
                 }
               };

You can see what it is trying to do.

The mySize function is to return the size of the object as given by the object's mySize property.  

If you try this out using say:

alert(myObject.getSize());

you will discover that you get an error message telling you that mySize is not defined. This is perfectly reasonable as mySize in the function's body either is a reference to a local or a global variable and clearly neither exist. 

To make the function into a proper working method we have to make mySize reference the property of the object called mySize. 

We can do this very easily and in the obvious, in fact far too obvious way using:

return myObject.mySize;

This works but it isn't a good way of achieving the result we are looking for.  Using the name of the object in a method isn't a good idea at all. 

The reason is that myObject isn't the name of the object in question. It just happens to be a variable that references the object at the moment. 

Consider:

var myObject = { mySize: 99,
                 getSize: function() {
                  return myObject.mySize;
                 }
               };
var myOtherObject=myObject;
var myObject={};
alert(myOtherObject.getSize());

All that happens here is that we set another variable to reference the object and use the original variable for something else i.e. to store an empty object.

Now the program still runs but the size is returned as undefined. 

You can't make use of the object's name in a method because the object doesn't have a name only variables that reference it and these can change at any time. 



Last Updated ( Friday, 05 September 2014 )
 
 

   
RSS feed of all content
I Programmer - full contents
Copyright © 2014 i-programmer.info. All Rights Reserved.
Joomla! is Free Software released under the GNU/GPL License.