1

Possible Duplicate:
Javascript: Module Pattern vs Constructor/Prototype pattern?

I want to use class emulation in javaScript. This is a preference.

I've been using the module pattern but am considering using just a simple function object as I can create public and private member variables and functions.

Here is an example of a function-object emulating a class:

var input = document.getElementById('input');
var output = document.getElementById('output');

function test()
{
    var private_var = 'private_var';
    var private_func = function(){ return 'private_func';};
    var my = {};
    my.public_var = 'public_var';
    my.public_func = function(){ return 'public_func';};
    return my;
}

var object_test = new test();

alert( '| ' + object_test.public_var);
alert( '| ' + object_test.private_var);

alert( '| ' + object_test.public_func() );
alert( '| ' + object_test.private_func() );

​

Here is an example of a the module pattern emulating a class.

What are the primary differences? Besides the ability to make implied global explicit, are there any?

Community
  • 1
  • 1
CS_2013
  • 1,158
  • 3
  • 13
  • 24

2 Answers2

2

I may be misunderstanding what you mean by "Function Object," but these patterns, as I understand them, aren't really interchangeable.

The "Module Pattern" is for defining a single object with methods and properties as desired. A good example of this is Math and a simple example of a custom module is just an Object instance:

var Module = { prop: 'prop' };
alert(Module.prop);

But, in this way, modules aren't classes. You don't have to call new Math to use them. You just call their methods (Math.abs()) or get/set their properties (Math.PI).

"Function Objects" -- or what I take to mean constructors -- are the closest concept to "class" definitions that JavaScript has. Object, String, Array. These and others are constructors defined for creating new instances.

The snippet you gave can certainly be revised to a constructor:

// common-practice: constructors are named in PascalCase
function Test()
{
    var private_var = 'private_var';
    var private_func = function(){ return 'private_func';};

    this.public_var = 'public_var';
    this.public_func = function(){ return 'public_func';};
}

var object_test = new Test();

Also, these patterns aren't necessarily even mutually-exclusive. Treating a constructor like a module would allow for defining "static"-like members:

var Foo = (function () {
    function constructor() {
        var private_var = 'private_var';
        this.public_prop = 'public_prop';
    }

    var private_shared = 'private_shared';
    constructor.public_shared = 'public_shared';

    return constructor;
})();

alert(Foo.public_shared);     // 'public_shared' (module property)
alert(new Foo().public_prop); // 'public_prop'   (instance property)
Jonathan Lonowski
  • 121,453
  • 34
  • 200
  • 199
0

I believe the main issue is that your test() function is still available to be called without the new keyword, and the value of 'this' in that case would point to the callee context (most likely global), not to the test() inner closure, causing undesired effects such as polluting the global namespace and different instances overwriting values of each other. The interpreter will not warn you if you call a constructor function as a regular function. If your code is not intended to be shared with a great audience and you are using some naming convention for constructor functions, such as Test() for constructors and test() for regular functions, you would be still safe. It helps also in keeping some discipline in code such as forcing you to define any 'public' members in the return statement, where all will be adjacent, acting as a clean façade. This is interesting in large code bases.