Reputation: 5010
Check out this piece of JavaScript code:
(function (w, d) {
var loader = function () {
var s = d.createElement("script"), tag = d.getElementsByTagName("script")[0];
s.src = "https://example.org/script.js";
tag.parentNode.insertBefore(s,tag);
};
w.addEventListener ? w.addEventListener("load", loader, false) :
w.attachEvent("onload", loader);
}) (window, document);
Why did the author of this code use this method to include a script in the document? And what is the usefulness of the line:
w.addEventListener ? w.addEventListener("load", loader, false) :
w.attachEvent("onload", loader);
Last point: I'm a JavaScript beginner, what is the (window, document)
at the end?
Upvotes: 2
Views: 285
Reputation: 116
The following addEventListener line is to register the function so that it gets called when the page finishes loading. Internet Explorer and Firefox (et al) use different functions to do this.
w.addEventListener ? w.addEventListener("load", loader, false) :
w.attachEvent("onload", loader);
In javascript a function is an object in and of itself. As such it's 'value' can be assigned to a variable or consumed immediately. To consume it immediately it must be wrapped in parentheses (otherwise it won't do what you want) and then call it like it were a regular function.
(function (w, d) { ... }) (window, document);
It's more obvious what is going on if we break it up across two lines.
var a = function(w, d){ ... };
a(window, document);
It was done this way to as to not pollute the global scope with temporary values or functions. Not to mention not trashing anyone else variables. This can be broken into two parts:
var loader
is in the closure's scope.Upvotes: 2
Reputation: 16456
I may be wrong, but this is the implementation used by Google with their analytics script.
This is called a closure, a function that is autoexecuted and enclose the variables inside, so they can't mess with your code.
This codes essentially creates a script tag and append this to the DOM before the first script tag it finds in the document.
The answer for the first question is about browser compatibility. some browsers use addEventListener
and others attachEvent
to attach events to elements in the page (in this case, the window) and it will lounch on the load event of the window (when all content is loaded, after the document is ready). Take a look at this for a more detailed answer: window.onload vs $(document).ready()
The second answer is simple. This are the parameters used in the closure (the auto calling function) and can be read in this way:
function anonymous(w, d) {
...
}
anonymous(window, document);
Upvotes: 1
Reputation: 1435
The window, document
at the end of the first block of code are arguments to the anonymous function defined in the rest of the code block. Since Javascript is pretty much a functional language programmers are allowed to define these anonymous functions and even use them without giving them a name.
The block of code you pasted with the question mark is an example of infix notation, a language construct that fits this pattern: condition ? ifTrueExpression : ifFalseExpression
. Where condition
is true, the entire expression will be equal to ifTrueExpression
. Otherwise, the entire expression will be equal to ifFalseExpression
.
The use of infix notation you pasted is common in detecting which type of internet browser is being used. Although, I'm not sure which browser this block of code is trying to detect, its intent is to implement an event handler in a browser specific way.
Upvotes: 1
Reputation: 18965
This is effectively the same as:
function RegisterEventListener(w, d) {
var loader = function () {
var s = d.createElement("script"), tag = d.getElementsByTagName("script")[0];
s.src = "https://example.org/script.js";
tag.parentNode.insertBefore(s,tag);
};
if (w.addEventListener) {
w.addEventListener("load", loader, false);
} else {
w.attachEvent("onload", loader);
}
}
RegisterEventListener(window, document);
The only real differences are:
function () {};
) without assigning it to anything it is only available for limited use (because there is no way to reference it). At the same time, anonymous functions also allow immediate execution (like the one in the code from your question function(a, b) {}(a, b);
.condition ? true : false
(tertiary operator) is just shorthand for writing simple if
statements so it requires less typing to write out, but some people also see it as being less readable.Upvotes: 1
Reputation: 3556
Adding the script that way allows the author to include that script in the document without directly editing HTML files. Can also be used to dynamically load a script only when needed. (i.e. if you have a bunch of code to edit something on the page, you don't want to download it until the user actually clicks the edit button, so you don't waste bandwidth when it's not needed).
addEventListener and attachEvent are ways to trigger a function to be called when the page has finished loading. In this case, there's a function named loader
The reason for both is that some browsers support one and some support the other. I've been using jQuery long enough that I don't remember which is which.
(window, document) is a way to encapsulate those variables in scope and/or refer to them by shorthand w and d. The author is creating a function that expects those parameters, then passing both window and document as the arguments for them.
The closure also helps the author keep from having his script clash with other scripts on the page. Think of every variable declared in there like it's a private variable in other languages.
Upvotes: 1
Reputation: 34038
The author of this code is using an anonymous function wrapped in a closure to fire off the function, which registers a load event. The script on the page will not actually be loaded until the window's onload event fires.
The reason that the author may be delaying the script load may be to give the web page more time to render before actually loading in the other script. This is a great technique to load page content quickly while delaying the loading of resources that are not immediately needed.
The technique the author is using is an anonymous function wrapped in a closure. Picture this:
myFunction (window, document);
Now, I'm going to replace the function call with an anonymous function:
function(w, d) {
// do stuff
alert("w = " + w);
alert("d = " + d);
}
Now I'm going to cause that function to run immediately, without actually giving it a name. I'm also going to pass two parameters into that anonymous function:
( function(w, d) {
// do stuff
alert("w = " + w);
alert("d = " + d);
}) ("1234", "5678");
The output in this example would be:
w = 1234
d = 5678
If you watch the parentheses and match them up, the first outer parentheses matches the closing parentheses on the last line at character 2, that is the function name, and the following set of parentheses wrap the two values passed into the function as parameters.
This can be a tough concept to grasp at first; after you see it done a few times, it starts to make more sense.
Upvotes: 1
Reputation: 807
So the function is wrapped in a closure. Which in turn means w = window
and d = document
.
When the method is called the it creates a function called loader
which is the callback for one of the two possible event listener triggers (meaning, that'll be called when the load
or onload
event is called on the window).
The x ? y : z
syntax is a shorthand if then else
call.
If we expanded that out, it'd look like this:
if (w.addEventListener) {
w.addEventListener("load", loader, false);
} else {
w.attachEvent("onload", loader);
}
that statement is used cater the method for both IE and other browsers.
Upvotes: 1
Reputation: 161
Firstly, w.addEventListener ?
to make sure if the browser supported the addEventListener method of window
Secondly, (window, document)
is just parameter call of anonymous function he wrote before function(w,d) {}
Upvotes: 2
Reputation: 6749
It looks like the author is waiting for the page to be fully loaded before attaching the script tag. addEventListener (DOM level 2) and attachEvent (Microsoft stuff) are more flexible ways of attaching events. The code is similar to saying w.onload = loader
.
The last bit is passing arguments into the anonymous function, where they are named w
and d
. By putting the () at the end, the anonymous function is invoked right away.
Upvotes: 1
Reputation: 78650
The first question, the code checks to see if window.addEventListener
is defined. If it is, it uses it, otherwise it uses window.attachEvent
. This is for browser compatibility.
The 2nd question, this code is an anonymous function which takes 2 parameters, w and d. This function is immediately called, passing the parameters window
and document
.
Upvotes: 3