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?

alex
  • 438,662
  • 188
  • 837
  • 957
Johnny Oshika
  • 45,610
  • 33
  • 151
  • 234
  • 6
    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. – Lee Kowalkowski Jul 03 '12 at 12:56
  • 1
    Why is it important to the question to specify "lower case f" ? – ClearCloud8 Apr 03 '13 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. – Stijn de Witt Jul 27 '13 at 01:43
  • 1
    related: [Is it right to think of a Javascript Function Expression that uses the 'new' keyword as 'static'](http://stackoverflow.com/q/10406552/1048572) on why this pattern [**should not be used**](http://stackoverflow.com/a/10406585/1048572) – Bergi Aug 19 '14 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 :) – Stijn de Witt Dec 08 '15 at 22:52
  • @StijndeWitt: Aren't the weird prototype inheritance and the leaked constructor reason enough? It might be simple, but it's invalid. What do you gain from this "pattern"? What purpose does it have for you? – Bergi Dec 09 '15 at 01:23
  • @Bergi What is so weird about prototype inheritance? Also calling the constructor 'leaked' is exaggeration imho; all constructor functions create objects that are 'leaking' the constructor function. I see no issue there. What I do see is a nice and succinct way to create a local scope that allows for information hiding and prevents pollution of the global scope. The fact that this function is used as a constructor means using `this` and no explicit `return` is needed. All in all a very elegant construct I would say. The regular IIFE looks horrible in comparison if you ask me. – Stijn de Witt Dec 09 '15 at 21:33
  • @StijndeWitt: The prototype is weird because it has no purpose. Creating a single instance only, nothing is shared anywhere. The prototype object is empty but for that constructor function, which *can* cause security and memory leaks. The point is that you shouldn't use a constructor at all if you only need an object. – Bergi Dec 09 '15 at 21:41
  • @StijndeWitt: I'd also expect engine deoptimisations due to the weird prototype usage, but I didn't test that yet. In any case, those constructed objects will need (a lot) more memory. Btw, if you don't like the IIFE pattern syntax, have a look at ES6 modules, block scopes, and arrow functions. – Bergi Dec 09 '15 at 21:51
  • @Bergi You have not yet addressed what is so 'weird' about calling a constructor function. And why would it take a lot more memory? What this fragment is doing is: Create an anonymous function, call it as a constructor (using `new`), use parentheses-less invocation and store the constructed object. Where is the weirdness. This is just the shortest way to write the above steps, but if someone had written them out in it's verbose form, would you call the resulting code 'weird' and 'invalid'? – Stijn de Witt Dec 09 '15 at 23:57
  • @Bergi and how exactly would the 'leaked' constructor function cause a security issue? If you had written `var someObj = function someObjCreator { ... }()` (not anonymous, auto-invoked function) would you claim that the function not being anonymous (and hence callable) would be a 'leak' and a 'security issue'? – Stijn de Witt Dec 10 '15 at 00:03
  • @Bergi The prototype object is just the (imho harmless) result of calling `new`, which *does* serve a very clear purpose: turn the function into a constructor, allowing for elegant code by using `this` and implicit return. Note how much shorter and more elegant (no local `instance` variable for example) this approach is compared to the IIFE described below. – Stijn de Witt Dec 10 '15 at 00:08
  • @StijndeWitt: A security issue can be caused if the attacker can run your initialisation again, or create multiple interfering instances, while you did not expect it. A memory leak can be caused if the constructor hangs onto some closure variable that the "instance" does not. You don't have that problem with an IIFE (regardless whether it's name or not) – Bergi Dec 10 '15 at 00:15
  • @StijndeWitt: The increased memory usage comes from the additional prototype object and the constructor function (which needs to be retained in memory, in contrast to an IIFE). Depending on the size of your object, and how often you run the code, this can incur significant overhead. – Bergi Dec 10 '15 at 00:18
  • @StijndeWitt: If you are looking for elegance of `this`, you can also simply use `var someObj = (function(){ …; return this; }.call({}));`. And you should never abuse syntax only because it makes code shorter, especially not when the result is not the same. That prototype is an *unwanted* side effect. – Bergi Dec 10 '15 at 00:20

3 Answers3

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.

Quamis
  • 10,181
  • 12
  • 45
  • 63
Christian C. Salvadó
  • 723,813
  • 173
  • 899
  • 828
  • 1
    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. – Clinton Pierce Feb 16 '10 at 17:16
  • 3
    I think you are missing a `return instance;` at the end. Otherwise, `someObj` will just be `undefined`. :-) – Matthew Crumley Feb 16 '10 at 17:27
  • 1
    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. – Stijn de Witt Jul 27 '13 at 01:48
  • Note that the parentheses surrounding the function declaration are unnecessary since the statement is already an expression due to the presence of `=` – Explosion Pills Aug 15 '13 at 18:39
  • @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. – xr280xr Dec 08 '15 at 14:14
  • the new keyword lets you add `public` members with this.NAME – Paul Totzke Mar 28 '16 at 13:43
  • "*The above code will produce an equivalent result.*" is wrong. Using `new` also constructs a prototype object that `someObj` will inherit from, and leaks the constructor function. – Bergi Jun 07 '17 at 14:00
15

Your code is just similar to the less weird construct

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

    ...
};
var someObj = new Foo;
kennytm
  • 469,458
  • 94
  • 1,022
  • 977
  • 9
    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. – kikito Feb 16 '10 at 17:41
  • 3
    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**. – J Bryan Price Dec 28 '12 at 20:48
  • @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. – Bill Yang Dec 03 '15 at 17:53
  • 1
    @BillYang That was 5 years ago. No idea. I haven't touched javascript ever since. – kikito Dec 03 '15 at 18:37
12

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.

Danubian Sailor
  • 21,505
  • 37
  • 137
  • 211
DUzun
  • 1,554
  • 16
  • 15