28

I have a JavaScript function object as;

var addNum = function(num1, num2) {
        return num1 + num2;
}

Now if I try to access

addNum.divide()

I wanted to understand the prototype chain for the above code. I read that in the above example, addNum would be searched for divide(), followed by Function.prototype and finally Object.prototype.

But my question is in the above example, how can addNum would be searched for divide()

Does it refer to something like ;

var addNum = function(num1, num2) {

this.divide = function(){}

            return num1 + num2;
    }

I could not understand the line where it says addNum would be searched for divide()

Please help me understand the same.

Fabian Schmengler
  • 24,155
  • 9
  • 79
  • 111
copenndthagen
  • 49,230
  • 102
  • 290
  • 442
  • I run your code in Chrome, and it says : Uncaught TypeError: Object function (num1, num2) { return num1 + num2; } has no method 'divide' – andri Mar 02 '13 at 12:04
  • Are you sure this isn't an architectural issue? In reality divide wouldn't be a child function of addNum. Rather they would have a parent class/object and they could share variables and properties and do maths on them? – Dominic Mar 02 '13 at 12:16
  • I read this line on http://doctrina.org/Javascript-Objects-Prototypes.html – copenndthagen Mar 02 '13 at 12:40
  • So, is what you suggested correct? `var addNum = function(num1, num2) { this.divide = function(){} return num1 + num2; }` I believe yes? – Weishi Z May 09 '16 at 22:46

5 Answers5

56

I'm not sure this will answer your question but may give you some insight. Consider the following example:

var Person = (function () {
    var Person = function (name) {
        this.name = name;
    }

    Person.greet = function () {
        console.log("Hello!");
    }

    Person.prototype = {
        greet: function () {
            console.log('Hello, my name is ' + this.name);
        }
    };
    return Person;
})();

var bob = new Person("Bob");

Person.greet(); // logs "Hello!"
bob.greet(); // logs "Hello, my name is Bob

The function object "Person" has a direct 'greet' property that is a Function. OOP-wise, you can almost think of that as a static method that can be called directly from the Person Function (Person.greet()). Once you "instantiate" a person object from the Person constructor, that new object "bob" now references it's methods from the Person.prototype object. Now when you call bob.greet(), it uses the greet function in the prototype object.

Hope that helps.

Keith Morris
  • 2,125
  • 1
  • 19
  • 21
  • I like this example, it really explains the possibilites of prototype inheritance well, perhaps if you would have added another bit that also explains that you can also now extend the `Function` constructor to further show the possibilites of Javascript and the idea behind prototypal inheritance. – gmaliar Mar 02 '13 at 12:28
  • 1
    thanks for the example. but why Person.prototype.constructor gets greet, but Person doesn't, please? if you type them into console – MartianMartian Mar 09 '18 at 11:36
26

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)

Community
  • 1
  • 1
Elias Van Ootegem
  • 74,482
  • 9
  • 111
  • 149
3

You can create divide as a [sort of a] static method:

var addNum = function(num1, num2) {
  addNum.divide = function(){return num1/num2;};
  return num1 + num2;
}
// now you first have to run addNum
var onethirds = addNum(1,3); //=> 4
addNum.divide(); //=> 0.333333...

But it's not advisable. Better create a constructor function:

function Pair(n1,n2){
   n1 = n1 || 1;
   n2 = n2 || 1;
   // create instance methods
   this.add      = function(){return n1+n2;};
   this.divide   = function(){return n1/n2;};
   this.multiply = function(){return n1*n2;}
}
var pair1 = new Pair(2,6)
   ,pair2 = new Pair(1,2);
pair1.add();    //=> 8
pair2.divide(); //=> 0.5
//etc.

or a more prototypal approach (methods are added to the constructor prototype, not to every instance):

function Pair(n1,n2){
   this.n1 = n1 || 1;
   this.n2 = n2 || 1;
   // create prototype methods (once)
   if (!Pair.prototype.add){
    var proto      = Pair.prototype;
    proto.add      = function(){return this.n1+this.n2;};
    proto.divide   = function(){return this.n1/this.n2;};
    proto.multiply = function(){return this.n1*this.n2;}
   }
}

Reading stuff

KooiInc
  • 119,216
  • 31
  • 141
  • 177
2

No, your last code only makes sense if you used addNum as a constructor function:

var instance = new addNum();
instance.divide();

However, because functions are objects, the following would be valid:

var addNum = function(num1, num2) {
        return num1 + num2;
}
addNum.divide = function() {}

In this case divide would be a property of addNum itself, not of one of its prototypes.

Fabian Schmengler
  • 24,155
  • 9
  • 79
  • 111
0

To understand prototypal inheritance is somewhat obscure at first, but think of it as the name suggests, there are a few prototypes in JavaScript and Function is one of them.

Whenever you create a new function you can check its type with the typeof command. In your case:

var a = function(a,b) { return a + b; }

It will return "function" so there are two ways to add to your a variable more methods. One would be, as @Keith Morris suggested, to create a new constructor and have its methods inside and return it. That is also the preferred way because then, you don't pollute the basic objects with prototypal methods which are extended to each and every object that is represented by them.

Meaning, if I instead do this:

Function.prototype.divide = function(a, b) { return a / b; }

I can now do a.divide(2, 1); and it would return 2. But for example if I use jQuery and do jQuery.divide(2,1) I will also get 2 because it tries to find it in the immediate scope of the function. If not, it will go to the prototype of it.

Hope this explains it to you a bit better.

ssc-hrep3
  • 15,024
  • 7
  • 48
  • 87
gmaliar
  • 5,294
  • 1
  • 28
  • 36