106

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?

15
  • 8
    I prefer your construct over the IIFE ('Immediately-Invoked Function'). 1: You don't need an explicit 'instance' object, that's exactly what 'this' is in JavaScript. 2: You don't need to return anything, which means, you don't need to remember to. Even the author of the accepted answer forgot to return the instance object initially! People usually prefer to use an IIFE if they hate new & this, with good reason - If you have a function handling a DOM event, this will refer to the element that fired the event, not your object, but you could just have var instance = this instead. Commented Jul 3, 2012 at 12:56
  • 1
    Why is it important to the question to specify "lower case f" ? Commented Apr 3, 2013 at 19:56
  • 7
    Because in Javascript there also exists the 'Function' function (with uppercase F), which is different: Function is a constructor function that can create new function objects, whereas function is a keyword. Commented Jul 27, 2013 at 1:43
  • 1
    related: Is it right to think of a Javascript Function Expression that uses the 'new' keyword as 'static' on why this pattern should not be used Commented Aug 19, 2014 at 11:28
  • @Bergi I read your links. I see no reason to discredit this pattern. It's valid. It's simple. So what's wrong. JSLint complains about everything BTW :) Commented Dec 8, 2015 at 22:52

3 Answers 3

64

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.

Sign up to request clarification or add additional context in comments.

7 Comments

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.
I think you are missing a return instance; at the end. Otherwise, someObj will just be undefined. :-)
May I suggest that if you care about modularity and information hiding, that you just give up on this and start using something like require.js? You're halfway there, why stop here? Asynchronous Module Definition (which is what require.js implements) supports this usecase and gives you a whole toolset to deal with scoping, namespacing and dependency management.
Note that the parentheses surrounding the function declaration are unnecessary since the statement is already an expression due to the presence of =
@StijndeWitt halfway there means you would need to do twice the work to use require.js but this might be all you need in simple cases.
|
15

Your code is just similar to the less weird construct

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

    ...
};
var someObj = new Foo;

4 Comments

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.
The OP's version could be reused via new someObj.constructor. Here the constructor is added to the namespace explicitly; the right style depends on the intended purpose of the function. Also, this style - though certainly the standard - lets someone populate the global namespace if they forget new before Foo.
@kikito what do you mean this does not allow reusing Foo for creating another object? var newObj = new Foo() should be creating a new instance.
@BillYang That was 5 years ago. No idea. I haven't touched javascript ever since.
13

To clarify some aspects and make Douglas Crockford's JSLint not to complain about your code here are some examples of instantiation:

1. o = new Object(); // normal call of a constructor

2. o = new Object;   // accepted call of a constructor

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

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

    this.set_inner = function (s) {
        inner = s;
    };
})(); // normal call of a constructor

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

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

    this.set_inner = function (s) {
        inner = s;
    };
}); // accepted call of a constructor

In example 3. expression in (...) as value is a function/constructor. It looks like this: new (function (){...})(). So if we omit ending brackets as in example 2, the expression is still a valid constructor call and looks like example 4.

Douglas Crockford's JSLint "thinks" you wanted to assign the function to someObj, not its instance. And after all it's just an warning, not an error.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.