0

I have seen the following style for returning a public interface from a constructor:

function AnObjectConstructor() {

    function localFunc() {};
    function publicFunc() {};

    // public interface
    var _this = {
        publicFunc: publicFunc
    };
    return _this;
};

I like this style because the public interface is clearly in one place and also localFunc can access publicFunc without using _this

This code can also be written like this:

function AnObjectConstructor() {

    function localFunc() {};
    function publicFunc() {};

    // public interface
    var _this = this;
    _this.publicFunc = publicFunc;
    return _this;
};

Both these forms are intended to be used with new:

var obj = new AnObjectConstructor();
obj.publicFunc();

I am not clear on whether these two forms are the same or not, and was hoping someone can help me with that ?

Also any general comments on this style will be appreciated..

alex
  • 479,566
  • 201
  • 878
  • 984
kofifus
  • 17,260
  • 17
  • 99
  • 173
  • Here's a related talk on inheritance: http://alexsexton.com/blog/2010/03/superclassy-inheritance-with-javascript-video/ and the classes http://alexsexton.com/inheritance/demo/ – Homer6 Jul 23 '13 at 02:45
  • Normally when you use constructor functions (using the new keyword) you're setting shared functionality on the prototype so they're not initialized for every instance. Maybe the following answer will be helpful: http://stackoverflow.com/questions/16063394/prototypical-inheritance-writing-up/16063711#16063711 JavaScript does not support private variables and trying to create them using closures comes at a cost. It's up to you to decide if it's worth it. – HMR Jul 23 '13 at 06:00

3 Answers3

4

Those two snippets are not doing the same thing. While both snippets have public references to publicFunc the first snippet returns an object literal and the second a reference to the function. Neither examples are examples are how you would create a function constructor. You need to use the new keyword to instantiate an instance of an object:

function AnObjectConstructor() {
    function localFunc() {};
    function publicFunc() {};
    // public interface
    this.publicFunc = publicFunc;
    //You don't need this line :return _this;
};

var obj = new AnObjectConstructor();

I also removed the creation of _this as there was no reason to create a local variable and assign this to it.

Edit

The second approach is preferred in my opinion, because it is the more conventional approach that leverages JavaScript's built-in capability of constructing objects. The first approach misses the point, because it is simply a function that returns a stripped down object literal.

marteljn
  • 6,446
  • 3
  • 30
  • 43
  • 1
    One problem with that is every constructed object will have its own `publicFunc` method, as opposed to placing it on its prototype so it's only ever created once. – alex Jul 23 '13 at 01:59
  • @alex that's not a problem, but a difference: the publicFunc is a public instance function (one per object), whereas in prototype defined are public shared functions (one for all objects instanceof ctor). – metadings Jul 23 '13 at 02:03
  • @metadings If you create 100 objects and the runtime doesn't do any optimisations for that, then you've got 100 functions living directly on each object, as opposed to once on the prototype. Is that not a problem, as well as a bad design decision? IMO, the constructed object should be lightweight as possible, common methods should exist once only the prototype. – alex Jul 23 '13 at 02:09
  • @alex I was simply illustrating how he could change his code to leverage the `new` keyword. I don't feel throwing in a micro-optimization, is going to answer the OP's question. – marteljn Jul 23 '13 at 02:09
  • @marteljn Sure, I understand. It was more for the OP to read than a criticism of your answer. – alex Jul 23 '13 at 02:09
  • I am sorry, I thought the name of the function would make it clear, my intention is for this object to be used only with new as in: var obj = new AnObjectConstructor(); Given that, is there any differences between the two forms ? is any one of them better ? and why do you say they are not good examples for constructors ? – kofifus Jul 23 '13 at 02:11
  • @user460084 You should edit your question if you have a correction, so it's not missed by anybody. – alex Jul 23 '13 at 02:12
  • @alex depends on what is to be done. in other languages there are also instance and static functions, in javaScript there are instance and shared functions. – metadings Jul 23 '13 at 02:13
  • @user460084 My opinion would be number two with the `new` keyword and removing `return this`. The first snippet all you are doing is returning an object literal that does not necessitate the rest of your function. That is to say, all of your private members are not being used. – marteljn Jul 23 '13 at 02:18
  • @metadings With late binding of `this` though, what is the advantage of direct assignment on the object? Even if you intended for some of the methods to be different, I still think it's better left on the prototype. Especially given that you can modify it later and have all *instances* reflect that, which isn't easily achieved if they're directly assigned. Maybe we can just agree to disagree. – alex Jul 23 '13 at 02:19
  • user460084 you're right that 'return _this;' is not needed in the second version, thx. metadings I don't really follow what you say ... I am trying to emulate c++ style class/public methods .. would using prototype be better ? – kofifus Jul 23 '13 at 02:31
  • 1
    @user460084 @alex is right that it is more optimal to do add public methods to the `prototype` property so they are only constructed once. However, the performance gain you will get from that is so negligible it is probably not worth worrying about. So essentially, either way is completely legitimate; choose the one you prefer just understand that you could use both approaches. – marteljn Jul 23 '13 at 02:36
  • thx user460084, if you want to post an answer explaining why the second one is better (without the 'return'), I can mark it as the acceptable answer – kofifus Jul 23 '13 at 02:40
  • @marteljn Performance gain isn't really the main reason to prefer it - it makes it easier to read the code (lightweight constructor) and less cluttered prototypes when examining them (with your brain and code). All my opinions, of couse. :) – alex Jul 23 '13 at 02:45
1

There is a difference. Your first constructor function could be invoked in two ways:

var myObject = AnObjectConstructor();

or

var myObject = new AnObjectConstructor();

This is because the first constructor function manually creates the returned object. In the case of the new operator, the this object that is automatically created by engine is effectively discarded when you return your own hand-made object.

However, your second constructor function relies on you invoking it with the new operator. If you do not use new, it will pollute the current this which could be another object or global space.

Peter
  • 3,998
  • 24
  • 33
  • am sorry, I thought the name of the function would make it clear, my intention is for this object to be used only with new as in: var obj = new AnObjectConstructor(); Given that, is there any differences between the two forms ? is any one of them better ? and why do you say they are not good examples for constructors ? – kofifus Jul 23 '13 at 02:14
0

When used with the new operator, they will indeed be the same (at least as far as how they're currently defined), as the specification says to set this to the newly constructed object when executing the constructor, or if an object is returned instead (your first example), to use that as the constructed object. The difference when returning your own object is that it won't have the [[prototype]] set to AnObjectConstructor.prototype.

In addition, if you call them without the new operator, then their behaviour will be very different. The first one will return a new object, much like a factory style method, but the second one will augment the global object, which is almost never what you want.

alex
  • 479,566
  • 201
  • 878
  • 984
  • I am sorry, I thought the name of the function would make it clear, my intention is for this object to be used only with new as in: var obj = new AnObjectConstructor(); Given that, is there any differences between the two forms ? is any one of them better ? and why do you say they are not good examples for constructors ? – kofifus Jul 23 '13 at 02:15
  • The first one is uncommon, and using `new` with it doesn't buy you any new functionality as opposed to just calling it, so I wouldn't use it. You should use your second form, but place any common methods on the prototype instead of directly on the constructed object. – alex Jul 23 '13 at 02:17