tags:

views:

83

answers:

6

So I've been looking into full development object oriented JavaScript practices, and wonder about the following examples.

As I understand it, (and it makes sense to me) that the following 'secret' field is 'private' :

var MyObject = function() {

    var secret = 'sshhh';

    this.getSecret() = function() {
        return secret;
    }

}

and this is because the field secret has function scope that the inner function can access, but nothing outside ... so far so good.

But I've seen the following around (and especially in Douglas Crockford's book) :

var MyObject = function() {

    var secret = 'sshhh';

    return {
       getSecret : function() {
            return secret;
       }
    }   

}();

and was wondering what the difference is, why is it better? I understand that in this case we're not even returning the same object that the private field exists in, but don't see a huge benefit as you can't access the field directly either way.

+1  A: 

In larger objects, having the returned object explicitly showing what is returned helps you see what is exposed in one place instead of worrying that you've missed a this.something.

andrewmu
So you're basically saying it's just a separation of the constructor from the final constructed object? For clarity reasons above everything else, as opposed to some kind of information hiding or something.
lucas1000001
No. I realise my explanation isn't great. What I'm trying to say it that both methods hide internal information, but the latter shows what is exposed more clearly. The function isn't a constructor as such in the second case, it just provides a scope for the hidden variables.
andrewmu
+4  A: 

Those examples are very different... The first creates a "MyObject" function that, when called as a constructor using new, will have a "getSecret" function as a property; the second creates a "MyObject" Object with a "getSecret" function as a property.

In that respect, this is sort of like the difference between a static method and a public method. In the first case, the method only exists when the constructor is called, not in the constructor itself. In the second case there is no constructor.

So let's say you have:

var MyObject1 = function() {
  var secret = 'sshhh';
  this.getSecret = function() {
    return secret;
  }
}

// ...

var MyObject2 = function() {
  var secret = 'sshhh';
  return {
    getSecret : function() {
      return secret;
    }
  }
}();

running some tests:

MyObject1.getSecret();
// TypeError: Object has no method 'getSecret'
var m1 = new MyObject1();
m1.getSecret();
// "sshhh"

MyObject2.getSecret();
// "sshhh"
var m2 = new MyObject2();
// TypeError: object is not a function

So MyObject1 is like a class, and MyObject2 is like a static class.

no
I don't think that's true of the first 'class' (if that's what you can call it). as I understand it, when you call `new MyObject()`, the 'this' property is changed from the global scope (as it is in function calls) to the object you're constructing. So this.getSecret will be attached to object not the global scope (Someone please comment if this is total crap!)
lucas1000001
Hang on, I'm still editing this, but I'm on a phone call ;)
no
Whoa sorry, sure the comment just totally changed (I'm sure it mentioned global scope before).
lucas1000001
Ah no probs sorry :)
lucas1000001
Ah I see - cheers for the info.I'm not sure I'd consider it a static class (as everytime you call MyObject2() you're getting a 'different' object (I'm not sure how to do identity in javascript but i'm sure MyObject2() == MyObject2() is not equivalent as far as identitiy goes.But like someone else mentioned I think a factory method is more like it.Either way the same principles hold - thanks
lucas1000001
I would add that MyObject2 is somewhat akin to a factory method that creates an object, if that helps at all.myObj = MyObject2(); myObj.getSecret(); // -> "sshhh"
Ryan Riley
;) Great minds think alike and all ...
lucas1000001
Ok, you get the prize, but one more quick question if ok? When would you use the factory approach over the 'class' approach. Is it just a matter of taste - or are there advantages to one over the other?
lucas1000001
actually `MyObject2()` was a bad cut-n-paste, should have been `MyObject2`. Stupid mistake. Shouldn't post answers during phone calls I guess. Edited...
no
BTW, check out this post if you want to see my attempt at emulating class-like oop in javascript... The macro stuff you can ignore, but you might be interested in some of the patterns there. http://stackoverflow.com/questions/3329094/
no
Cool thanks - this may be a good candidate answer for my next question that's out there - cheers
lucas1000001
+1  A: 

It's not any better - or worse. Its used in two different scenarios.

The first example you give would work well for using the function as a 'class':

 stuff = new MyObject();

The second example works well for defining an inline object with some functions on it / a "singleton".

gnarf
+1  A: 

If you want some more information on it there is an article referring to it as the revealing module pattern:

http://www.klauskomenda.com/code/javascript-programming-patterns/#revealing

spinon
+1  A: 

They're functionally the same, at least when it comes to calling new MyObject().getSecret();. The only difference is that the latter does not need to be called with new because it is essentially a "factory method" and creates the object for you.

Loren Segal
*functionally* the same? `new MyObject().getSecret()` vs. `MyObject.getSecret()` don't seem like the same thing to me...
gnarf
Perhaps you're confused about the word "functionally". As in, they both perform the exact same function of creating a new object and returning the secret attribute. Syntax is not part of "function".
Loren Segal
A: 

All I can say is that the first example is way simpler to implement. Consider, the first variable is a function that returns a simple string with MyObject().

The second returns an object, which returns the "secret" with MyObject.getSecret().

So, I'd rather get the "secret" from the function by calling the former example (which requires less code to do the exact same thing), if that's what you mean by "better."

Perhaps Crockford had a bigger idea when he used the second example.

pop850