|Written by Ian Elliot|
|Monday, 26 March 2018|
Page 2 of 3
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 as a namespace but a simple Function object even when assigned as a property isn't a method.
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:
which returns the size of the object computed in some way appropriate to the object. Ask yourself what does:
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
is the same as:
both of which return the size of the object in some appropriate way.
Yes absolutely right and it's not really an objection.
As described earlier 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.
Consider for a moment a simple example of a function as an object property:
You can see what it is trying to do.
The getSize function is to return the size of the object as given by the object's mySize property.
If you try this out using say:
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:
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.
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.
This is the problem that we encountered in Chapter 5, objects are anonymous.
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.
The Solution - this
The solution to the problem of how to reference the object that the method is a property of is a very simple one - the call context.
When you evaluate a Function object that is a property of an object the built in variable "this" is set to reference the same object.
That is, when you write:
this is set to reference the same object as myObject by the system. If you write:
this is set to reference the same object as myOtherObject no matter what that object might be.
So what this means is you can now write the getSize method as:
Now when you write:
this is set to the same object as myObject and the method is equivalent to:
and all without actually using the myObject variable in the code.
If you use this in the method’s code then it clearly doesn’t matter what variable you use to reference the object as this will reference the same object.
Simple, elegant and it works - as long as you understand it and use it properly.
In chapter 2 is was stated that outside of a function this references the Global object and now you can see that this is logical. Outside of a function the Global object is the object that can be considered to call all the other functions.
When a Function object is called as the property of another object then this is set to reference that object.
When a Function object is called not as a property of another object then this is set to the global object.
There is an important subtlety here.
Function objects are late bound
A Function object exists in its own right and not as part of some other object.
When you create a Function object as a property of another object the Function object exists as an independent entity and how it is evaluated depends on how it is used. A Function object can have many references to it and some of these might be as properties of another object and some might be global.
Whether a Function object is treated as a function or a method depends on how you reference it.
The Function object the getSize property references is created when the object that myObject references is created - but it is just a normal object that happens to be a Function object. The second statement of the program sets myFunction to reference that same Function object.
Now if you call the function using
this references the same object that myObject references and so the function works correctly as a method bound to myObject.
If you call the function using:
this will be set to reference the Global object and in this case the function will be evaluated as if all its variables were global. In this case, of course, the function will not work because there is no global variable called mySize.
The point is that Function objects exist independently of other objects and as a result a given Function object can be a method bound to an object when called in one way and not a bound method when called in another.
Yet another way of putting this is that Function objects are late bound to any objects that might use them as methods i.e. what this references is only determined when the function is evaluated and it can change dynamically.
A Function object always has an independent existence from any other object. This means that it can be evaluated in its own right and this will be set to the global object in this case. In this case this is usually a problem!
It can also be evaluated as a property of any other object and in this case this is set to reference that object.
A Function object can also be a method for lots of different objects at the same time. Of course all of those objects have to have at least the properties that the function makes use of or the function has to test for the existence of those properties before it makes use of them.
|Last Updated ( Tuesday, 01 May 2018 )|