Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

A few questions about how JavaScript works

I have been looking deeply into JavaScript lately to fully understand the language and have a few nagging questions that I can not seem to find answers to (Specifically dealing with Object Oriented programming).

Assuming the following code:

function TestObject()
{
    this.fA = function()
    {
        // do stuff
    }

    this.fB = testB;

    function testB()
    {
        // do stuff
    }
}

TestObject.prototype = {
    fC : function 
    {
        // do stuff
    }
}

What is the difference between functions fA and fB? Do they behave exactly the same in scope and potential ability? Is it just convention or is one way technically better or proper?

If there is only ever going to be one instance of an object at any given time, would adding a function to the prototype such as fC even be worthwhile? Is there any benefit to doing so? Is the prototype only really useful when dealing with many instances of an object or inheritance?

And what is technically the "proper" way to add methods to the prototype the way I have above or calling TestObject.prototype.functionName = function(){} every time?

I am looking to keep my JavaScript code as clean and readable as possible but am also very interested in what the proper conventions for Objects are in the language. I come from a Java and PHP background and am trying to not make any assumptions about how JavaScript works since I know it is very different being prototype based.

like image 928
KayoticSully Avatar asked Sep 07 '12 05:09

KayoticSully


2 Answers

What is the difference between functions fA and fB

In practice, nothing. The primary difference between a function expression (fA) and a function declaration (fB) is when the function is created (declared functions are available before any code is executed, whereas a function expression isn't available until the expression is actually executed). There are also various quirks associated with function expressions that you may stumble across.

In the example, I'd use a function expression, simply because declaring a function expression, then assigning the result seems a bit abstracted. But there is nothing "right" or "wrong" about either approach.

If there is only ever going to be one instance of an object at any given time, would adding a function to the prototype such as fC even be worthwhile?

No. Just about everyone who goes does inheritance finds that plain objects are often simpler and therefore "better". Prototype inheritance is very handy for patching built–in objects though (e.g. adding Array.prototype.each where absent).

And what is technically the "proper" way to add methods to the prototype…

There isn't one. Replacing the default prototype with some other object seems like a bit of a waste, but assigning an object created by a literal is perhaps tidier and easier to read that sequential assignments. For one or two assignments, I'd use:

 Constructor.prototype.method = function(){…}

but for lots of methods I'd use an object literal. Some even use a classic extend function and do:

myLib.extend(Constructor.prototype, {
    method: function(){…}
});

Which is good for adding methods if some have already been defined.

Have a look at some libraries and decide what you like, some mix and match. Do whatever suits a particular circumstance, often it's simply a matter of getting enough code to all look the same, then it will look neat whatever pattern you've chosen.

like image 80
RobG Avatar answered Oct 05 '22 12:10

RobG


fA and fB are effectively the same and it is just a matter of convention.

If there is only one instance of a object I wouldn't even use a constructor function, but rather just a object literal, such as:

var o = {
   fA: function () { ... },
   fB: function () { ... },
   fC: function () { ... }
};

As for adding it to an instance or a prototype, the instance is slightly more efficient than adding it to the prototype if you only have one instance but, as I said, use a literal instead.

I avoid declaring functions in the constructor because each invocation of the constructor will create new object representing each function. These objects are not very large they tend to add up if many objects are created. If the functions can be moved to the prototype, it is much more efficient to do so.

As for adding to the prototype, I favor the

TestObject.prototype.functionName = function () { };

style but it is a matter of preference. I like the above because it looks the same whether you are extending the prototype or creating the intial prototype.

like image 22
chuckj Avatar answered Oct 05 '22 13:10

chuckj