From the DailyJS "Let's build a JavaScript Framework" I'm not quite sure on the following code, obviously used as a global abatement technique.
My understanding so far balks at (function(){}) . I understand setting the turing var up, setting global.turing to turing, and return either window or this (if not in a browser), but the (function(global){})(this or window) thing confuses me...I've seen things like
var mything = {}
and setting all your code up under mything, but this idiom confuses me a little.
I really want to understand the reasoning here vs memorizing that it "works out"
(function(global) {
var turing = {
VERSION: '0.0.1',
lesson: 'Part 1: Library Architecture'
};
if (global.turing) {
throw new Error('turing has already been defined');
} else {
global.turing = turing;
}
})(typeof window === 'undefined' ? this : window);
This is an anonymous or lambda function. Most languages support this.
Using an anonymous function is really a matter of preference for the author. Without setting up an anonymous function to deal with the return value of a prior call, you would have to allocate additional memory on the client side by initializing a variable to contain the returned object and then pass it to a globally declared function later on in a serial manner.
If it is a 1 time function, it saves space, memory, time.
As a side-note: You can probably get a better feeling for this by googling around for some of the concepts behind functional programming. Lambda functions seem to be all the rage lately, especially in Python.
(This answer is over 4 years old (as of April, 2015) and while it's still correct I think it needs a more general explanation - see below)
Original answer
Think of this:
as:
but without the need to give it a name (like functionName).
So this:
is really just:
It is a function with one argument (called
global
within the function) and it is called withtypeof window === 'undefined' ? this : window
which means the same as:but using a shorter notation (and without naming the function).
More general explanation
I wrote this answer over 4 years ago and I think it's time to add some more general explanation of the concepts that are involved here.
As I explained above, this:
is an anonymous version of this:
which (if you call it only once) is usually (see below for exceptions) also the same as this:
Going back to the anonymous immediately invoked function, this:
is the same as this:
which may be have a more obvious meaning for most people. (Here the immediately invoked function has no arguments and serves only the purpose of giving us an isolated scope for variables and other nested functions, so that we don't pollute the outer or global scope - which is also the main reason of using arguments in immediately invoked anonymous functions in the first place.)
On parentheses
By the way, this:
is the same as this:
The parentheses around the function are required because of a language ambiguity but they may include the
()
that actually invoke the function or they may not - though some people argue that the second form here looks more clear. See this explanation by Douglas Crockford for more details and why he thinks that the first version looks like "dog balls."Exceptions
Previously I said that this:
is the same as this:
and this is most of the time true for one argument (that doesn't mask the variable of the same name in the outer scope while depending on its value at the same time) and usually true for more than one argument (if they don't depend on each other as well). I hope it will get more clear on the examples.
When we have this code:
then we can't translate it into:
because in the first version we add 1 to the outer
x
and bind the result to the innerx
and as soon as we get inside the function we have only the innerx
to work with (and even the newlet
statement will not help us with that).Another example:
Here you can set
old_x
to the value ofx
from the outer scope andx
in the inner scope to a new value of 1, and you don't have to worry about the order. But if you did:Summary
So as you see there are some situations where you cannot simply translate:
into:
but I would argue that if it can be translated into the second form then it should be for readability. Especially for larger functions it is inconvenient that you have to scroll to the end of the function to know what the variable used at the top of the function mean.
Back to the question
That means that I would translate this code from the question:
into this:
I hope this answer explains why those two are equivalent, and that it could even be written as:
and it would still mean the same, while being much less readable at the same time.
See also my other answer where I explain similar concepts.