Introduction To Javascript Functions
Introduction To Javascript Functions
JavaScript Functions
DECLARING A FUNCTION
Advertisement
There are several ways to declare a function. All valid, but there are differences on
how they're handled in the background.
functionName([parameters]){functionBody};
Example D1
function add(a, b)
{
return a+b;
}
alert(add(1,2)); // produces 3
Run example.
Example D2
var add=function(a, b)
{
return a+b;
}
alert(add(1,2)); // produces 3
Run example.
This code does the same thing as the previous example. The
syntax may seem odd, but it may make more sense when you
consider that a function is an object, and we're just assigning a
name to the object. Think of it as saying var myVar=[1,2,3]; The
content of functions declared this way is also compiled. FastClick Ad Network
When assigning a function like this, we are not restricted to an unnamed function. Here, I did the same
thing as ExampleD2, but I added "theAdd" as the function name, and I can refer to the function by the
name or by the variable.
Example D2A:
var add=function theAdd(a, b)
{
return a+b;
}
alert(add(1,2)); // produces 3
alert(theAdd(1,2)); // also produces 3
Run example.
The ability to declare function in this way is useful in object oriented programming, because we can have
a function be a property of an object, like this.
We can also declare a function using the "new" operator. This is the least common way of
declaring a function and is not recommended unless there is a specific reason to use it (see
below for possible reasons). The syntax is as follows:
Example D3:
Run example.
Here I have 2 parameters named a and b, the functionBody returns the sum of a and b. Note
that "new Function(...)" uses capital F, not lower case f. This tells JavaScript that we want to
create an object of type Function. Note also that the parameter names and the function body
are passed as Strings. We can have as many parameters as we want, JavaScript knows that the
function body is the String right before the closing bracket. (If there's no parameter, you can just
have the function body.) You do not have to put everything on a single line (use "\" or use String
concatenation "+" to separate long code). The "\" sign tells JavaScript to look for the remaining of
the string on the next line. An example is shown below.
Example D4
Run example.
Declaring function in this way causes the function not to be compiled, and is potentially slower
than the other ways of declaring functions. To see why, consider this code:
Example D5
function createMyFunction(myOperator)
{
return new Function("a", "b", "return a" + myOperator + "b;");
}
Run example.
That interesting example creates 3 different functions during runtime by passing a parameter
which will be used to build a new Function. Since the compiler has no way of knowing what the
final code will look like, the content of new Function(...) is not compiled. What good is this for?
Well, an example of where this feature might be useful is when you want to allow the user to
create their own function; such as in a game. We might want to allow user to add "behaviors" to a
"player." But again, in generally, we should avoid using this format unless there's a specific
purpose.
FUNCTION AS AN OBJECT
Function is a special kind of object in JavaScript, it's a first class data type. That means we can add
properties to it. Here are some interesting points to note:
We can add properties to Objects, including function objects. Since the act of declaring a
function creates an object. We can, potentially add properties to that function. For
example, here we declare function Ball, and added callsign property.
Example 3
function myFunction(message)
{
alert(message);
}
var ptr=myFunction; // ptr points to myFunction
ptr("hello"); // executes myFunction which will prints "hello"
Run example.
We can execute the function as if the function name has been replaced by the pointer name. So
above, the line ptr("hello"); has the same meaning as this: myFunction("hello");
function sayName(name)
{
alert(name);
}
var object1=new Object(); // creates 3 objects
var object2=new Object();
var object3=new Object();
object1.sayMyName=sayName; // assign the function to all objects
object2.sayMyName=sayName;
object3.sayMyName=sayName;
Since only pointer is stored (not the actual function itself), when we change the function
object itself, all pointers pointing to that function will see the changes. We can see it here:
Example 5:
function myFunction()
{
alert(myFunction.message);
}
myFunction.message="old";
var ptr1=myFunction; // ptr1 points to myFunction
var ptr2=myFunction; // ptr2 also points to myFunction
We can reassign function after you created it, but we need to refer to the function object
itself, not a pointer to it. For example, below I changed the content of myfunction().
Example 6:
function myFunction()
{
alert("Old");
}
myFunction(); // prints "Old"
myFunction=function()
{
alert("New");
};
myFunction(); // prints "New"
Run example.
Where has the old function gone? Into oblivion.
Example 6A:
function myFunction()
{
alert("Old");
}
var savedFuncion=myFunction;
myFunction=function()
{
alert("New");
};
myFunction(); // prints "New"
savedFuncion(); // printf "Old"
Run example.
Be careful, the example below won't work because instead of modifying the function, the
code below creates another function which is called myFunctionPtr.
Example 6B:
function myFunction()
{
alert("Old");
}
var savedFunc=myFunction;
savedFunc=function()
{
alert("New");
};
myFunction(); // prints "Old"
savedFunc(); // prints "New"
Run example.
We can nest a function within a function. For example, below I have a function called
getHalfOf, and within it I have another function called calculate.
Example 7
var result="";
result+=calculate(num1)+" ";
result+=calculate(num2)+" ";
result+=calculate(num3);
}
var resultString=getHalfOf(10,20,30);
alert(resultString); // prints "5 10 15"
Run example.
You can only call a nested function locally. That is, you cannot call: getHalfOf.calculate(10)
because calculate only exists when the outer function (getHalfOf()) is run. This is consistent
with our discussion above (function is compiled, but not executed until you call it).
You might be wondering about naming collision. For example, which calculate function
will be called below?
Example 8
function calculate(number)
{
return number/3;
}
var result="";
result+=calculate(num1)+" ";
result+=calculate(num2)+" ";
result+=calculate(num3);
}
var resultString=getHalfOf(10,20,30);
alert(resultString); // prints "5 10 15"
Run example.
In cases like this, the compiler will first look on the local address space, so it will use the nested
calculate function. If we erase the nested/local calculate function, then that code will use the
global calculate function.
Let's look at another special feature of a function that makes it unique among other object types. A
function can be used as a blueprint for a data type. This feature is commonly used in object oriented
programming to simulate user defined data type. Objects created with user defined data type is usually
referred to as user defined objects.
By declaring a function, we have also created a new data type. The data type can be
used to create a new object. For example, below I created a new data type named Ball:
Example DT1
function Ball()
{
}
var ball0=new Ball(); // ball0 now points to a new object
So what does "ball0=new Ball()" do? The "new" keyword creates a new object (named
ball0) of type Object. It then executes: Ball(), passing the reference to ball0 as the
calling object. Below, you will see the message: "creating new Ball" if indeed Ball() is
executed.
Example DT2
function Ball(message)
{
alert(message);
}
var ball0=new Ball("creating new Ball"); // creates object &
// prints the message
ball0.name="ball-0"; // ball0 now has a "name" property
alert(ball0.name); // prints "ball-0"
Run example.
We may consider the red portion of the above code as a shortcut for doing the same
thing as below:
Example DT2A
function Ball(message)
{
alert(message);
}
var ball0=new Object();
ball0.construct=Ball;
ball0.construct("creating new ball"); // executes ball0.Ball("creating..");
ball0.name="ball-0";
alert(ball0.name);
Run example.
The line ball0.construct=Ball has the same syntax as ptr=myFunction in Example 4.
Review Example 4 also if you're not sure what the line after that means. Note: You might
be thinking of doing ball0.Ball("...") directly, but that won't work, because ball0 have no
property named Ball("...") and it won't know what you're trying to do.
When we create an object using the new keyword like above, a new Object is created.
We can add properties to the object after the creation (such as when I added "name"
property above. The problem with that approach is that if we create another instance of
the object, we need to add the property again to the new object like below.
Example DT3 (creates 3 ball objects)
function Ball()
{
}
var ball0=new Ball(); // ball0 now points to a new instance of type Ball
ball0.name="ball-0"; // ball0 now has a "name" property
Remember that the "new" keyword eventually causes the constructor function to be
executed. In this case, it will executel Ball("creating new Ball", "Soccer Ball"); and the
keyword this will refer to ball0.
Therefore, the line: this.name=specifiedName becomes ball0.name="Soccer Ball".
It basically said: add "name" property to ball0, with the value of "Soccer Ball."
So now, we've just added a name property to ball0, much like what is being done in
previous examples, but in much more elegant and extensible way. Now, we can have as
many balls and as many properties as we want without having to add them manually.
Also, people wanting to create a Ball object can easily see the constructor function and
easily find out all the properties of a Ball. Let's add more properties to Ball.
Example DT5
Whew! In object oriented term, you can say that Ball is an object type which has the
following properties: name, color, owner, weight.
We are not limited to adding simple data types such as Strings or numbers as properties.
We can also assign objects as properties. Below, supervisor is a property of
Employee. Example DT6
Any kind of object can be a property, in fact, recall from Example 4 (not Example DT4)
above, that a function is also an object. So you can make a function a property of an
object. Below, I added 2 functions getSalary and addSalary
Example DT7
this.addSalary=addSalaryFunction;
this.getSalary=function()
{
return this.salary;
};
}
function addSalaryFunction(addition)
{
this.salary=this.salary+addition;
}
Let's see what the differences are. Below, take a look at the red portion of the same
example from above. When this piece of code is executed, getSalary function is
declared. As have been mentioned several times, a function declaration causes an
object to be created. So by the time boss is created (after the green line below), boss
has a property called getSalary somewhere.
this.addSalary=addSalaryFunction;
this.getSalary=function()
{
return this.salary;
};
}
function addSalaryFunction(addition)
{
this.salary=this.salary+addition;
}
this.addSalary=addSalaryFunction;
this.getSalary=function()
{
return this.salary;
};
}
function addSalaryFunction(addition)
{
this.salary=this.salary+addition;
}
this.addSalary=addSalaryFunction;
this.getSalary=getSalaryFunction;
}
function getSalaryFunction()
{
return this.salary;
}
function addSalaryFunction(addition)
{
this.salary=this.salary+addition;
}
Here, both functions are pointing to one location, which saves space and construction
time (especially if you have a lot of nested functions in the constructor function). There
is another feature of a function that may used to improve this design. It is called
"prototype," and we'll talk about it on the next section.
FUNCTION PROTOTYPE
Every constructor function has a property named prototype. This property is very useful to declare
variables or functions that are common to a particular class.
You do not need to explicitly declare a prototype property, because it exists on every
constructor function. You can see this below:
Example PT1
function Test()
{
}
alert(Test.prototype); // prints "Object"
Run example.
As you've seen above, prototype is an object, therefore, you can add properties to
it. The properties you added to prototype will become common properties of all objects
created using the constructor function.
For example, below I have a Fish data type. I want all fishes have these properties:
livesIn="water" and price=20; to accomplish that, I can add those properties to
prototype of the constructor function: Fish.
Example PT2
You can use prototype to assign functions that are common on all objects, too. This has
the benefit of not having to create and initialize the property every time you construct an
object. To illustrate this, let's revisit Example DT9 and rewrite it using prototype like
below:
Example PT3
Employee.prototype.addSalary=function addSalaryFunction(addition)
{
this.salary=this.salary+addition;
}
We can create the objects as usual
Here's an illustration of how prototype works. Each instance of the object (boss1,
boss2, boss3 has an internal property named __proto__, which points to the prototype
property of its constructor (Employee). When you execute either getSalary or
addSalary, the object finds it on it's __proto__, and executes the code. Note that here,
there's no code duplication (compare with diagram at Example DT8).