When we declare function like
this, the content of the function is compiled (but not executed until
we call the function). Also, you might not
know it, but an object with the same name as the function is created.
In the above example, we have an object named
"add" (for more on this, see Function as an Object section
below.)
We can also declare a function by assigning a variable to an
unnamed
function.
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.
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.
var myObject=new Object();
myObject.add=function(a,b){return a+b};
// myObject now has a property/a method named "add"
// and I can use it like below
myObject.add(1, 2);
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:
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
var add=new Function("a", "b",
"alert" + // chop string using "+"
"('adding '+a+' and ' +b);\ // separate string using "\"
return a+b;");
alert(add(3,4)); // produces 7
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;");
}
var add=createMyFunction("+"); // creates "add" function
var subtract=createMyFunction("-"); // creates "subtract" function
var multiply=createMyFunction("*"); // created "multiply" function
// test the functions
alert("result of add="+add(10,2)); // result is 12
alert("result of substract="+subtract(10,2)); // result is 8
alert("result of multiply="+multiply(10,2)); // result is 20
alert(add);
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:
As mentioned briefly before, when we declare a function, JavaScript
actually creates an object for you in the background. The name of
the object is the function name itself. The type of the object
is function. In the example
below, we might not realize it, but we actually have created an object called:
Ball.
Example 1
function Ball() // it may seem odd, but this declaration
{ // creates a object named Ball
i=1;
}
alert(typeof Ball); // produces "function"
We can even print the content of the object and it will output
the actual code of the function: Example 2: Click alert(Ball);
to see content of Ball.
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 Ball() // it may seem odd, but declaration
{ // creates an object named Ball, and you can
} // refer to it or add properties to it like below
Ball.callsign="The Ball"; // add property to Ball
alert(Ball.callsign); // produces "The Ball"
Since function is an object, we can assign a pointer to a
function.
For example, below, the variable ptr points to myFunction
object. Example 4
function myFunction(message)
{
alert(message);
}
var ptr=myFunction; // ptr points to myFunction
ptr("hello"); // executes myFunction which will prints "hello"
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");
Pointer to a function is useful in object oriented programming.
For instance: when we want
several objects to point to the same function like below:
Example 4A
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;
object1.sayMyName("object1"); // prints "object1"
object2.sayMyName("object2"); // prints "object2"
object3.sayMyName("object3"); // prints "object3"
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
ptr1(); // prints "old"
ptr2(); // prints "old"
myFunction.message="new";
ptr1(); // prints "new"
ptr2(); // prints "new"
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"
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"
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
function getHalfOf(num1, num2, num3)
{
function calculate(number)
{
return number/2;
}
var result="";
result+=calculate(num1)+" ";
result+=calculate(num2)+" ";
result+=calculate(num3);
}
var resultString=getHalfOf(10,20,30);
alert(resultString); // prints "5 10 15"
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;
}
function getHalfOf(num1, num2, num3)
{
function calculate(number)
{
return number/2;
}
var result="";
result+=calculate(num1)+" ";
result+=calculate(num2)+" ";
result+=calculate(num3);
}
var resultString=getHalfOf(10,20,30);
alert(resultString); // prints "5 10 15"
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.