As you say so yourself: you have a function object. Functions are objects in JS, just like Object literals, arrays, or anything else: a function can be assigned properties and methods at will:
var someAnonFunction = function(foo)
{
console.log(this);
console.log(this === someAnonFunction);//will be false most of the time
};
someAnonFunction.x = 123;//assign property
someAnonFunction.y = 312;
someAnonFunction.divide = function()
{
console.log(this === someAnonFunction);//will be true most of the time
return this.x/this.y;//divide properties x & y
};
someAnonFunction.divide();
In this case, the function object, referenced by someAnonFunction
has been assigned a reference to the anonymous function, called divide
(well, the reference to an anonymous function was dubbed divide anyway). So there is no prototype involvement at all here. Mind you, as you say so yourself: all objects can be traced back to Object.prototype
, just try this:
console.log(someAnonFunction.toString === Function.prototype.toString);//functions are stringified differently than object literals
console.log(someAnonFunction.hasOwnProperty === Object.prototype.hasOwnProperty);//true
Or, perhaps this is more clear: a simple scheme of how a method/property call is resolved to a value in JS:
[ F.divide ]<=========================================================\ \
F[divide] ===> JS checks instance for property divide | |
/\ || | |
|| || --> property found @instance, return value-------------------------------| |
|| || | |
|| ===========> Function.prototype.divide could not be found, check prototype | |
|| || | |
|| ||--> property found @Function.prototype, return-----------------------| |
|| || | |
|| ==========> Object.prototype.divide: not found check prototype? | |
|| || | |
|| ||--> property found @Object.prototype, return---------------------|_|
|| || |=|
|| =======>prototype is null, return "undefined.divide"~~~~~~~~~~~~~~~|X|
|| \ /
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~< TypeError can't read property 'x' of undefined
It therefore follows, that if you want the code above to work using prototypes, you'll have to augment a prototype of sorts (in this case, the Function.prototype
). Do know that this isn't to be recommended, in fact changing "native" prototypes is often frowned upon. Still:
Function.prototype.divide = function (a, b)
{
a = +(a || 0);//coerce to number, use default value
b = +(b || 1) || 1;//division by zeroe is not allowed, default to 1
return a/b;
};
function someFunction ()
{
return 'someString';
};
var another = function(a, b)
{
return a + b;
};
someFunction.divide(12, 6);//will return 2
another.divide(12, 4);//3
In both cases, the function object, referenced by the name (someFunction
or another
) will be scanned for a property called divide
, which isn't found. Then however it'll scan the Function.prototype
, where such a property is found.
If that weren't the case, JS would also check the Object.prototype
, if that failed, it will eventually throw an error.
I've posted quite lengthy answers on SO on this subject a while back:
What makes my.class.js so fast? (deals with prototype chains)
Objects and functions in javascript (recap of functions <=> objects <=> constructors)
What are the differences between these three patterns of "class" definitions in JavaScript? (some more info, still)
Javascript - Dynamically change the contents of a function (vaguely touches on the anonymous functions, assigned to variables and properties and changing their context)