4

While I am learning about javascript closure, I ran into an example on w3schools that uses immediately executed functions to provide private variables for functions:

var add = (function () {
    var counter = 0;
    return function () {return counter += 1;}
})();

but to me, all immediately executed function does is executing the statements in the body, which, if I recall correctly can be accomplished by the keyword new

var add = new function () {
    var counter = 0;
    return function () {return counter += 1;}
};

document.write("return" + add()+ "<br>"); // return 1
document.write("return" + add() +"<br>"); // return 2, works the same as the example on w3school

new is obviously more complicated, it creates a new object...but I think you are not obligated to use that object (add a return statement at the end).

My question is: what can be done with immediately executed function but not by keyword new? or can you always replace the 1st using the later?

watashiSHUN
  • 9,684
  • 4
  • 36
  • 44
  • 3
    Stay as far from 'W3Schools' as possible if you really wanna learn JS. – Nonemoticoner Mar 09 '16 at 23:59
  • 1
    They are not self-invoking, they are immediately executed. Being self-invoking means that it invokes itself (recursion for example does that), while in your code it does not. – zerkms Mar 10 '16 at 00:03
  • @zerkms thanks, I am just citing W3School – watashiSHUN Mar 10 '16 at 00:09
  • Now the 2 options are not comparable: it's not obvious why you even need `new` if you don't have a constructor. – zerkms Mar 10 '16 at 00:12
  • @djechlin I read that thread before, and it is why I believe **new** can _replace_ the immediately executed functions – watashiSHUN Mar 10 '16 at 00:12
  • Immediately executing tells it all - you're going to run that code immediately. What's the purpose of doing `new` if you're performing setup and returning something else? I would think that's the better question, e.g., `new` is the special case, not `(function(){})()`. – Jared Farrish Mar 10 '16 at 00:13
  • 1
    "I believe new can replace the immediately executed functions" --- it cannot, they are different. IIFE creates a scope, `new` creates objects using a constructor. The purposes are entirely different. – zerkms Mar 10 '16 at 00:13
  • @zerkms isn't a "constructor" in javascript just a function definition? in other words...you can use new in front of any function definition – watashiSHUN Mar 10 '16 at 00:16
  • 1
    @watashiSHUN you can, but the intentions become unclear: you can use `+` instead of `*`, but you would not do that would you? – zerkms Mar 10 '16 at 00:18
  • @zerkms, could you elaborate on the scope? maybe an example? – watashiSHUN Mar 10 '16 at 00:19
  • The purpose of IIFE is to create a local scope not available from anywhere else. Your code is an example of that. `var counter` is placed in an isolated scope. – zerkms Mar 10 '16 at 00:19
  • I *really* like this idea. I'm definitely going to wrap some libraries in my next personal project with `new function() { ... }`. +1 for the thought! (I'd want to benchmark it before production use, but this should be harmless, and it's really pretty syntactically clean.) – Jeremy Mar 10 '16 at 00:21
  • 2
    @JeremyBanks it's not clean: it confuses the intention and the implementation. "clean" code is the one that expresses the intentions explicitly, with the idioms and semantics your code provides. From that perspective - "create a new instance using a constructor" and "just invoke a function" are 2 different tasks performed using 2 different language constructs. – zerkms Mar 10 '16 at 00:22
  • 1
    @zerkms - I am pretty sure Jeremy Banks was being facetious. – Jared Farrish Mar 10 '16 at 00:23
  • @JaredFarrish ohhhhh, thanks. I'll keep my comment though, since I like it anyway ;-D – zerkms Mar 10 '16 at 00:23
  • @zerkms, but new also has a local scope? are you saying that we can access counter in my second example? good analogy with "+" and "*", but replace multiplication with addition comes with a performance cost...here if new and IIFE both execute the statements, they are more interchangable? – watashiSHUN Mar 10 '16 at 00:24
  • @zerkms I wasn't joking, but I definitely did mean to qualify "clean" as "syntactically clean" -- fixed. :P I would not use this in production code because it's misleading/unconventional, but I *am* going to use this for fun in my next entirely-personal project. – Jeremy Mar 10 '16 at 00:24
  • @watashiSHUN "but new also has a local scope?" --- this makes no sense. `new` "has" no any scope, it's a function that does have. `new` is just an operator that invokes a function but does not create any scopes itself. "but replace multiplication with addition comes with a performance cost" --- performance it's not a subject here, but clarity is. https://en.wikipedia.org/wiki/Rube_Goldberg_machine - it also does the job, but through some indirections. – zerkms Mar 10 '16 at 00:24
  • @zerkms right, so...the scope comes with the function, when I have `function(){...}();` wrapped around my code...it provides scope, but isn't it the same with `new function(){};`? – watashiSHUN Mar 10 '16 at 00:30
  • @watashiSHUN it is the same. In both cases it's a `function` that creates a new scope. What is different is "intention" ("I'm doing it because I want to ..."). In case of the `new` the intention is: I'm using a constructor to construct an object. In case of the IIFE: I'm using IIFE to isolate some data in its own scope. – zerkms Mar 10 '16 at 00:31
  • 2
    @zerkms, you said "The purpose of IIFE is to create a local scope not available from anywhere else", it can also be achieved by using new as well, so functionality wise, IIFE is replaceable? – watashiSHUN Mar 10 '16 at 00:33
  • @watashiSHUN - Using `new` in the case where an IIFE *suffices* is like buying a semi-trailer when a call to Uber would do. – Jared Farrish Mar 10 '16 at 00:35
  • @watashiSHUN it's not - the only current answer has provided an example that not every function may functionally behave the same if invoked immediately or `new`ed – zerkms Mar 10 '16 at 00:35

1 Answers1

3

f() and new f are almost identical (compare this and that). Of course, new does a lot more work preparing an object you're going to throw away.

You cannot blindly replace f() with new f if

  • you're using this in f (obviously)
  • you're returning non-objects

For example, these two calls will produce different results:

x = 5 + (function () {
    return 123;
})();

y = 5 + new function () {
    return 123;
};

In other cases, if you don't mind wasting resources and validators shouting at you, new is fine.

georg
  • 211,518
  • 52
  • 313
  • 390
  • 3
    I'd say that using `this` after invoking with `new` is actually *safer* than using `this` in a standard IIFE, because there's no risk of accidentally hitting the global namespace. :) – Jeremy Mar 10 '16 at 00:22
  • @JeremyBanks: the point is, if you use `this`, these two forms are not equivalent. – georg Mar 10 '16 at 00:26
  • interesting...can you explain the behavior of your second example, where new function tries to returns a primitive? I just ran a test, the type of the return value is an object – watashiSHUN Mar 10 '16 at 00:43
  • 2
    @watashiSHUN: if you return a scalar, `new` ignores it and returns `this`, the newly constructed object. – georg Mar 10 '16 at 01:01
  • @JeremyBanks: However, [using `new` with a function expression is an absolutely horrible practice](http://stackoverflow.com/a/10406585/1048572) :-) – Bergi Mar 10 '16 at 01:30