Everytime you call a function, an arguments property object gets generated. You can call it directly to see how many arguments you have passed to the function:
arguments.length
Remember that arguments is not a real array, even though it behaves like one, but you can always use the power of prototype and apply to make it behave like one:
Array.prototype.slice.call(arguments, 1)); // Tricking slice() to take arguments as a real array here
function range(start, end) { if (arguments.length < 2) { end = start; start = 0; }
The other thing that gets implicitly passed to functions is “this”, as the context of the function
apply is just a way to pass context to a function. But it also allows you to pass the context of “this” as an argument. Same with call, examples:
function run(from, to) {
alert("The ", this.adjective, " rabbit runs from ", from, " to ", to, "."); }
run.apply(whiteRabbit, ["A", "B"]);
run.call(fatRabbit, "the cupboard", "the fridge");
} // Both produce the same result, apply passes an argument
So, when you create an object using the “new” keyword. The function name will also have its own prototype space, on top of the already inherited Function object:
function Rabbit(adjective) {
this.adjective = adjective;
}
// functions in the prototype namespace will be present in all objects you spawn with new Rabbit("arg1");
Rabbit.prototype.speak = function(line) {
echo("The ", this.adjective, " rabbit says '", line, "'");
};
Some things to take into account:
1) Defining functions the "traditional" way, will result on those functions being a method of the window (Global) object. By traditional I mean not as part of another object, straight out as:
function noModule() { return this; }
now: window.noModule is defined.
2) Now, the beauty of this: if you define an object, and assign noModule to it, the context of 'this' change to the context of the object the function is attached to:
myDefinedObj.noModule = noModule;
noModule(); // Will return myDefinedObj instead of window
3) When you want to switch the context of 'this' from window to another object, but don't want to attach your function as a permanent method in the object at hand, you can use call() or apply():
noModule.call(myDefinedObj); // Will return myDefinedObj, or used internally for any definitions inside the function
4) Don't forget functions have an implicit constructor object, if you use it, at runtime you will generate a brand new 'this' associated with the function:
var newFunction = new noModule(); // Even if there was no implicit return, you will be returning 'this' as the internal context of the new instance of the function just created, not window
Note: convention calls for noModule to be NoModule when used this way. Just as a reminder this is a constructor, not a function. Also, if you find yourself returning something in the function, this may not be a good candidate for a Constructor, since the idea of a constructor is to return "this" implicitly.
5) Meet bind(). This is a function that takes an object as an argument, and makes sure that object will be the context everytime a function is called:
noModule.bind(myDefinedObj); // From now on, noModule returns noModule instead of window
bind also takes arguments to be binded to the function, not only the 'this'. But performance is poor, in which case you may as well use call or apply if you can.
curry() is simmilar to bind, but does not take 'this' or any object to define context. It just binds arguments to a function.