views:

362

answers:

3

My colleague has been using "new function()" with a lower case "f" to define new objects in JavaScript. It seems to work well in all major browsers and it also seems to be fairly effective at hiding private variables. Here's an example:

    var someObj = new function () {
        var inner = 'some value';
        this.foo = 'blah';

        this.get_inner = function () {
            return inner;
        };

        this.set_inner = function (s) {
            inner = s;
        };
    };

As soon as "this" is used, it becomes a public property of someObj. So someObj.foo, someObj.get_inner() and someObj.set_inner() are all available publicly. In addition, set_inner() and get_inner() are privileged methods, so they have access to "inner" through closures.

However, I haven't seen any reference to this technique anywhere. Even Douglas Crockford's JSLint complains about it:

  • weird construction. Delete 'new'

We're using this technique in production and it seems to be working well, but I'm a bit anxious about it because it's not documented anywhere. Does anyone know if this is a valid technique?

Thanks in advance, Johnny

+11  A: 

I've seen that technique before, it's valid, you are using a function expression as if it were a Constructor Function.

But IMHO, you can achieve the same with an auto-invoking function expression, I don't really see the point of using the new operator in that way:

var someObj = (function () {
    var instance = {},
        inner = 'some value';

    instance.foo = 'blah';

    instance.get_inner = function () {
        return inner;
    };

    instance.set_inner = function (s) {
        inner = s;
    };

    return instance;
})();

The purpose of the new operator is to create new object instances, setting up the [[Prototype]] internal property, you can see how this is made by the [Construct] internal property.

The above code will produce an equivalent result.

CMS
The ECMAScript 262 Specification in Section 13 explains this a little more formally. Something like `function foo () {}` returns the result of creating a `Function` object [presumably with new Function ()]. It's syntax sugar.
clintp
I think you are missing a `return instance;` at the end. Otherwise, `someObj` will just be `undefined`. :-)
Matthew Crumley
@Matthew: Yes, I missed the `return` statement, thanks.
CMS
+3  A: 

Your code is just similar to the less weird construct

function Foo () {
    var inner = 'some value';
    this.foo = 'blah';

    ...
};
var someObj = new Foo;
KennyTM
It is not just similar, it does exactly the same thing... with the sole exception that they will not be able to reuse Foo for creating another object.
egarcia
A: 

You don't need to introduce a second object- just return the constructor itself.

var someObj= (function(){
 var inner= 'some value';
 this.foo= 'blah';
 this.get_inner= function(){
  return inner;
 }
 this.set_inner= function(s){
  inner= s;
 }
 return this;
})();

someObj.set_inner('some other value');

alert(someObj.get_inner())

kennebec
Yes, but since you're calling it as a function (and not a constructor) `this` refers to the global object... which means you're polluting `window` with `foo`, `get_inner` and `set_inner`...
J-P
Not so good: foo, get_inner and set_inner are thus global and someObj just equals the global object. (But inner is still closed).
machine elf
@J-P, you beat me to it =)
machine elf
You're both right- thanks for pointing it out.
kennebec