We will understand the functions a bit so that it is a little clearer.
In javascript we have the "function declaration" which are the functions that are declared with the keyword function and a name
function miFuncion(parametro){...}
We also have the "function expression" that we usually know as anonymous functions
var miFuncion = function(parametro){....}; //Creamos la funcion
miFuncion(algunValor); //La ejecutamos
This last one is the one that is used as a self-executable (IIFE) enclosing the declaration of the function between parenthesis and putting right away, in parentheses, the values that will be passed to the anonymous function, if the empty parentheses are put obviously we are running it without parameters.
The previous anonymous function would look like this:
(function(parametro){...})(algunValor);
var algunValor = 10;
console.log("Mi valor original es: " + algunValor);
(function(parametro){ parametro += 20; console.log("Dentro de la funcion anonima vale: " + parametro); } )(algunValor);
console.log("Mi valor original fuera de la funcion anonima es: " + algunValor);
To answer the question of how does the function receive the parameters?
(function(window, document){ })(window, document);
Let's write it in this way, which is common to find to reduce the size of a script
(function(w, d){ })(window, document);
Our anonymous function asks us for two variables w and d and we are passing it to it as window and document values of the global scope respectively.
That way we can occupy only the variable d within our anonymous function and not document, so the weight of the file will be less
(function(w, d){ d.getElementById('elemento'); })(window, document);
Another reason why you use window and document sent as parameters is because javascript manages local variables better than global variables, so your script performs better, but you will only notice if you have very complex scripts with many calls a window and document.
IIFE functions are self-executing when the browser finds the line where that function is, if you look for a DOM element in the anonymous function before the safe DOM tree is loaded you will not find it, but if you run your function at the end of your document you will have your complete DOM tree.
Now, do not confuse the DOM tree with the window and document objects since the latter are created when any window is created and the DOM tree is created when the entire HTML document is read. Then it does not matter where you execute your anonymous function you will always have the window and document objects ready.