admin管理员组

文章数量:1410682

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 e 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.

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 e 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.

Share Improve this question edited Sep 7, 2012 at 15:12 Robert Harvey 181k48 gold badges348 silver badges513 bronze badges asked Sep 7, 2012 at 5:15 KayoticSullyKayoticSully 1,4006 gold badges15 silver badges30 bronze badges 6
  • Javascript != Object oriented. As you (correctly!) observed, Javascript is arguably better characterized as a "prototypical" language. Strong, strong book remendation: Javascript, the Good Parts, Douglas Cockford. IMHO... – paulsm4 Commented Sep 7, 2012 at 5:18
  • Great question, wrong place to ask. You'd do better asking this kind of question over in programmers.stackexchange. – Jeremy J Starcher Commented Sep 7, 2012 at 5:18
  • paulsm4: I do understand that, I am just trying to understand JavaScript from that angle as well for the sake of pleteness. And thanks for the book suggestion! @JeremyJStarcher: Thanks! I honestly didn't even know that existed. – KayoticSully Commented Sep 7, 2012 at 5:23
  • 3 @paulsm4 - Why isn't JavaScript object oriented? A language doesn't have to have classes and class-based inheritance to be considered OO. – nnnnnn Commented Sep 7, 2012 at 6:03
  • @KayoticSully You shouldn't post the same question across Stack Exchange sites. Pick a site and run with it. 'Shopping the question' is frowned upon. You also posted this question here: programmers.stackexchange./questions/164029/… – George Stocker Commented Sep 7, 2012 at 10:47
 |  Show 1 more ment

4 Answers 4

Reset to default 6

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.

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.

Also are there any definitive JavaScript style guides or documentation about how JavaScript operates at a low level?

Damn no javascript programmer should ever miss "Professional JavaScript for Web Developers". This is a fantastic book, that goes into the deep. It explains objects, class emulation, functions, scopes and much much more. It is also a JS reference.

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?

As for the way to define classes, I would remend to have a look at various JS MVC frameworks (like Spine.js, which is lightweight ). You do not need the whole of them, just their class emulation libraries. The main reason for this, is that JS does not have the concept of classes, rather it is purely consisted of objects and prototypes. On the other hand classes can be perfectly emulated (please do not take the word emulated as it is something missing). As this needs some discipline from the programmer, it is better to have a class emulation library to do the job and make you code cleaner.

The standard methods that a programmer should expect of a class emulation library are:

// define a new Class
var AClass = Class.create({
   // Object members (aka prototype), 
   // usually an initialize() method is called if it is defined 
   // as the "constructor" function when a class object is created
}, {
   // Static members
}); 

// create a child class that inherits methods and attributes from parent
var ChildClass = AClass.extend({
   // Child object members
},{
   // Child static members
}); 

AClass.include({
   // Object amendments (aka mixin), methods and attributes 
   //   to be injected to the class object
},{
  // Statics amendments, methods and attributes to be 
  //  injected as class static members
});


// check object type
var aObj = new AClass();
aObj instanceof AClass; //  true
aObj instanceof ChildClass; //  false


var cObj = new ChildClass();
cObj instanceof AClass; //  true
cObj instanceof ChildClass; //  true

I answer for first part: there is no differences, when you declare function not as variable then declaration of it rises in the block, so

...
func();
...    
function func () { ... }

is equal to

var func = function () { ... };
...
func();
...

So your code

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

is equal to

function TestObject () {
    var testB = function () { // do stuff };    
    this.fA = function () { // do stuff };
    this.fB = testB;
}

本文标签: oopA few questions about how JavaScript worksStack Overflow