A function in JavaScript can be either named or anonymous. Any function can be assigned to a variable or passed to a method, but passing member functions this way can cause them to be called in the context of another object (i.e. with a different "this" object).
function named() {}
var handler = function() {}
You see a lot of anonymous functions in jQuery code:
$(document).ready(function() {});
$("a").click(function() {});
$.ajax({
url: "someurl.php",
success: function() {}
});
The type of a function is "function".
Arguments
Inside a function a special variable "arguments" is always available. It's similar to an array in that it has a length property, but it lacks the built-in methods of an array. The elements of the pseudo-array are the argument of the function call.
function log(x) {
console.log(typeof x, arguments.length);
}
log(); // "undefined", 0
log(1); // "number", 1
log("1", "2", "3"); // "string", 3
The arguments object also has a callee property, which refers to the function you're inside of. For instance:
var awesome = function() { return arguments.callee }
awesome() == awesome // true
Context, Call and Apply
In JavaScript, the variable "this" always refers to the current context. By default, "this" refers to the window object. Within a function this context can change, depending on how the function is called.
All event handlers in jQuery are called with the handling element as the context.
$(document).ready(function() {
// this refers to window.document
});
$("a").click(function() {
// this refers to an anchor DOM element
});
You can specify the context for a function call using the function-built-in methods call and apply. The difference between them is how they pass arguments. Call passes all arguments through as arguments to the function, while apply accepts an array as the arguments.
function scope() {
console.log(this, arguments.length);
}
scope() // window, 0
scope.call("foobar", [1,2]); // "foobar", 1
scope.apply("foobar", [1,2]); // "foobar", 2
Scope
In JavaScript, all variables defined inside a function are only visible inside that function scope. Consider the following example:
// global
var x = 0;
(function() {
// private
var x = 1;
console.log(x); // 1
})();
console.log(x); // 0
It defines a variable x in the global scope, then defines an anonymous function and executes it immediately (the additional parentheses are required for immediate execution). Inside the function another variable x is defined with a different value. It is only visible within that function and doesn't overwrite the global variable.
Closures
Closures are created whenever a variable that is defined outside the current scope is accessed from within some inner scope. In the following example, the variable counter is visible within the create, increment, and print functions, but not outside of them.
function create() {
var counter = 0;
return {
increment: function() {
counter++;
},
print: function() {
console.log(counter);
}
}
}
var c = create();
c.increment();
c.print(); // 1
The pattern allows you to create objects with methods that operate on data that isn't visible to the outside—the very basis of object-oriented programming.
Proxy Pattern
Combining the above knowledge gives you as a JavaScript developer quite a lot of power. One way to combine that is to implement a proxy pattern in JavaScript, enabling the basics of aspect-oriented programming (AOP):
(function() {
// log all calls to setArray
var proxied = jQuery.fn.setArray;
jQuery.fn.setArray = function() {
console.log(this, arguments);
return proxied.apply(this, arguments);
};
})();
The above wraps its code in a function to hide the "proxied"-variable. It saves jQuery's setArray-method in a closure and overwrites it. The proxy then logs all calls to the method and delegates the call to the original. Using apply(this, arguments) guarantees that the caller won't be able to notice the difference between the original and the proxied method.

