Both of the following code snippets worked:
Using IIFE in js file:
(function initialize() {
txtInput = document.getElementById('txtInput');
txtResult = document.getElementById('txtResult');
txtInput.value = "0";
txtResult.value = "0";
}());
Calling initialize() on window load event in html file:
window.addEventListener('load', initialize, false);
Is one a better approach than other; in terms of performance or otherwise? As it stands right now, I am leaning more towards adding event listener to the window object, because it is more readable.
It depends when you want the code to run. If you want the code to execute ASAP you can use an IIFE but there is really no point using an IIFE if you don't use it to protect your variables and/or not polluting the global scope.
(function initialize() {
// do somthing
}());
or
// do somthing
will execute at the same point in time.
If you want to defer execution there are three points in time usually used by web devs. <script>s at bottom, DOMContentLoad and window.onload.
<script>s at bottom will execute after they are fetched from the server.
DOMContentLoaded basicly execute as soon as </html> has been read by the HTML parser.
very simplified window.onload executes after all CSS, <img>es and <script>s have been loaded.
Note that in reality, with attributes like async and defer on <script>s, this is more complex, . This is why there is a mountain of resource loaders available.
Probably the result of each approach matters, not the performance. The first approach runs immediately while the second one waits until dom is ready. The end result is that in your first approach, you may end up getting undefined for both textInput and textResult, unless you place the script on the bottom of page.
The IIFE in a script element (whether inline or external loaded) just before the closing body element certainly appears most clever. It confuses the hell out of commoners.
document.addEventListener('DOMContentLoaded', function() ... is easy to understand. It's almost plain English: event listens for DOM content loaded. So, poof, the majesty is gone. Note this is distinct from window onload.
I use the event listener, as it adheres to the KISS principle, it's a purpose built tool, and it does what it says it does (which probably includes stuff/functionality I haven't even considered).
Related
So, I've been trying to understand a specific js library by running it through my browser's debugger, and something happens that just confuses me.
I first encountered this in the Phaser game library, but I've seen it another library as well. I'll use Phaser as an example:
<script>
(function(){
var game = new Phaser.Game(800, 600, Phaser.CANVAS, '');
game.state.add('Game', Game);
game.state.start('Game');
})();
</script>
So that anonymous function finishes setting some things up, and I step over and out of that function, and after a couple more steps (the pointer just sitting at the top of the html doc in the meantime) my program out of nowhere ends up here:
Phaser.Device._readyCheck = function () {
var readyCheck = this._readyCheck;
....
}
It didn't look like anything within my flow of control called that function, so how did I get here? What's calling this function? I've read a bit about 'asynchronous functions' and that sounds like a pretty good explanation, but the stuff I've glanced at on Google don't really explain anything well, so I can't say I understand it enough to be sure. I'm relatively new to JavaScript.
The library sets up event handlers for various events which then get called asynchronously. In this case, event handlers are setup to to watch for the completion of the loading of the DOM, among other things, so that the internal state of the library can be initialized. You can see how it happens in the source
src/system/Device.js:Phaser.Device._readyCheck
and Phaser.Device.whenReady in the same file. With a little searching you can easily find who calls whenReady.
The function you pointed out at the top is a self-executing function. (); causes everything contained in the preceding parentheses to be executed immediately.
I have come across some code using $(window).ready() that does dome UI resizing and positioning on HTML elements. I wondering why it is used? Is there an advantage to using it this way?
Are there any advantages over $(document).ready()?
The advantage of ready over the load event is that it fires as soon as the DOM is ready, without waiting for the distance resources (mainly the images) to be loaded. Usually you just want to be sure the elements are present, so that you can bind to them, but you don't need the distance resources to be loaded.
From the documentation :
In most cases, the script can be run as soon as the DOM hierarchy has
been fully constructed
$(window).ready() and $(document).ready() are equivalent.
From the source code :
ready: function( fn ) {
// Add the callback
jQuery.ready.promise().done( fn );
return this;
},
You see that the argument isn't even used, it's just returned so that you can chain if you want. You could have done this :
$({}).ready(function(){
...
});
But you shouldn't worry and should use the shortcut :
$(function(){
// your code which needs the DOM here
});
I looked at the jQuery 1.9.0 source code, and it doesn't look like the .ready() method uses at the object it was applied to; it has document hard-coded throughout it. So all $(anything).ready(...) calls are equivalent.
Download the source code and see the definition of jquery.ready.promise, this is where most of the work of $(...).ready() is done.
The documentation makes it clear that $(window).ready() doesn't have a defined meaning:
The .ready() method can only be called on a jQuery object matching the current document, so the selector can be omitted.
Currently the object is ignored, the above allows them to change this behavior in the future, since it shouldn't impact any correctly-written code.
I saw an answer to some question earlier that used my "Weird" example, and I was wondering if there was any benefit to either method.
Some HTML:
<span id="them">Hey</span>
<span id="me">Hey</span>
What is the difference between:
(function()//doing this
{
them.innerHTML = "Weird<br>";
})();
me.innerHTML = "Not so weird<br>";//and doing this
And even, why do people use window.onload when they can put scripts at the bottom of the body? Or is it just a matter of personal preference?
Your first code snippet: is a Module Pattern Or Immediately Invoked Function Expression(IIFE)
(function()//doing this
{
them.innerHTML = "Weird<br>";
})();
This when encountered by the Javascript compiler will immediately invoke the function when it encounters (); and keeps the variables and functions within its scope.
You must read Java-script Design Patterns to better understand its use and benefits.
Second code snippet: is just a JavaScript statement.
me.innerHTML = "Not so weird<br>";//and doing this
This when encountered by the JavaScript compiler will immediately execute it.
Remember both snippets executions depends on where its placed.
So, to answer your other question. window.onload is an event fired when the HTML DOM is fully loaded and browser can read all its elements.
There is no difference between your two examples. Your first example creates an anonymous function that immediately executes (called an Immediately Invoked Function Expression). Your second example just executes the same code.
You have to wait until a browser reads all the HTML elements before you can change them with JavaScript. The onload event fires when the page has fully loaded and at that time the browser knows about all the HTML elements. However, a browser won't fire the onload event until after the page has fully loaded, which means the browser will wait until after a large image has fully loaded -- even though the browser has already parsed the rest of the HTML -- making your JavaScript needlessly wait until the image finishes loading. Because the browser knows about all the HTML before the image finishes loading there is no reason to prevent JavaScript from executing earlier.
Once people discovered that onload was waiting too long before allowing the JavaScript to execute, people started putting their JavaScript right before the closing <body> tag (without using onload), so that the JavaScript would execute as soon as all the HTML had been parsed (except for the closing <body> tag), and that way their JavaScript could start executing sooner than when using window.onload.
Now JavaScript libraries like jQuery have an event that fires when the browser knows about all the HTML -- even though the page hasn't fully loaded (e.g. due to images that haven't fully loaded).
In your simple example, there is no difference between the result of the two cases. Both accomplish the same thing.
The reason for using this structure:
(function()//doing this
{
them.innerHTML = "Weird<br>";
})();
Is to create a function scope that can be used to hold private or temporary variables or to create a closure without exposing the variables inside to the outside world.
As for your second question, window.onload fires at a different time than scripts placed at the end of the body because window.onload fires when all synchronous resources needed by the page have finished loading (like scripts and images). It can be used, either to get notified when all these resources are done loading or it can be used by code that cannot be easily located at the end of the body as a safe time when the page is ready though it is usually not necessary to wait that long just for the DOM to be safe.
In the above case there is not advantage in using the first method.
But the first method is preferable in scenarios where you need to create some variables/method but does not want to pollute the global name space
After some thought, there is a benefit over writing the extra (function(){})(); as shown (imagine the code is huge):
(function()
{
var text = "Span 'them' text!";
them.innerHTML = text;
//Many lines of code
})();
(function()
{
me.innerHTML = text;//will throw 'text is undefined'
//Many lines of code
})();
This will be quite handy for debugging many lines of code, the debugger would recognise the error and "point" straight to it.
Whereas with this example:
var text = "Span 'them' text!";
them.innerHTML = text;
//Many lines of code
//...
me.innerHTML = text;
Your "error" (which the debugger is perfectly happy with) would be much harder to track down.
I am new to oop in js. I'm working on a HTML5 game using Box2dWeb and I decided that I should it make it completely oop based. So I created a physics class like this in a separate file called physics.js
(function(window)
{
function Physics(element, scale){
//init world logic
}
Physics.prototype.debug = function(){
//debug draw logic
};
Physics.prototype.step = function(dt){
//step logic
};
//making this class(or object) visible on the global scope
//so i can create vars of this type anywhere in the application
window.Physics = Physics;
}(window));
Now I have a main game.js file where I init all my game physics, graphics, assets, etc. Here are the contents:
(function(){
function init(){
var physics = new Physics(document.getElementById("b2dCanvas"), 30);
console.log(physics);
physics.debug();
}
window.addEventListener("load", init);
}());
This file, initializes my Physics object without any problem. Ultimately this is what i want. Great! But, prior to this, the file was like this, without the init() function.
(function(){
var physics = new Physics(document.getElementById("b2dCanvas"), 30);
console.log(physics);
physics.debug();
}());
This apparently threw the error Uncaught TypeError: Cannot call method 'getContext' of null. This meant, the physics constructor was being called(and naturally element at this point was null) without me invoking it. How was that possible? My self-executing function in game.js should have initialized the Physics object right? What am I missing?
Your script was running before the HTML was fully parsed, and before your canvas element was added to the DOM. When you added window.addEventListener("load", init);, you made it run when the window.onload event was triggered. At that moment, the DOM was fully parsed.
In modern browsers, you could also replace that with
document.addEventListener("DOMContentLoaded", init);
That event will trigger when the DOM is ready, but doesn't wait for other resources like images (unlike onload).
Or, just add all your scripts just before closing the body tag. At that point, every HTML tag in the body will already have been inserted into the DOM.
This meant, the physics constructor was being called(and naturally
element at this point was null) without me invoking it. How was that
possible?
Becase you are calling it, using this syntax:
(function(){...}());
^^
call
That will call the function when the script is parsed as part of the normal page script parsing, and will not wait for the document/DOM to be ready for you to manipulate. You'll want to either use some sort of document 'load' listener, or remove that particular syntax and call the function manually when you're sure the DOM is ready.
My guess is that you're calling the function before the DOM is ready. Put the script include at the bottom of your code or even better just wrap all init a window load listener.
The error has nothing to do with the Physics object not being ready. It has to do with the code inside of it trying to reference an element that is not on the page when the code is called.
It is simple you were calling
document.getElementById("b2dCanvas")
before the element was loaded on the page. When getElementById does not find anything it returns null.
So what your code looks like if you were to inspect it
var physics = new Physics(null, 30);
and element is null
function Physics(element, scale){
var ctx = element.getContext("2d"); //<-- where the error occurs since element is null
Hence the error: Uncaught TypeError: Cannot call method 'getContext' of null.
When you listen for the load event, that means the element is there so it loads with no problem. Other way of dealing with it is to add the script to the bottom of the page.
I'm binding the window.onload event like this
// It's a little more complex than this, I analyze if there is any other function
// attached but for the sake of the question it's ok, this behaves the same.
window.onload = myfunction;
Onload is triggered twice on my local machine a several times on the production server
If I change it by the jQuery equivalent
$jQuery(window).load(myfunction);
It behaves as expected (executed only once).
Could you help me to understand possible reasons why the first option it's not working as supposed?
Thanks!
The parentheses on your assignment — myfunction() — executes your function. You haven't shown what myfunction does, but this means that the return value from that function is being assigned to window.onload, not the function itself. So, I don't know how that is getting executed, unless you have somehow got that to work, like ending the function with return this;
You want
window.onload = myfunction;
Given the nature of window.onload, it seems unlikely that pure browser events alone are making both calls to myfunction. Therefore, a breakpoint inside your function will help you see the call stack. I've included screenshots for Chrome.
Sample code:
var alertme = function() {
alert("Hello");
}
window.onload = alertme;
function testsecondcall() {
alertme();
}
testsecondcall();
Open your page in Chrome.
After the page has loaded once, open the Developer Tools panel and put a breakpoint on the line inside your function, then refresh the page.
Check the call stack of both times that it breaks. One will be empty (the actual window.onload). The other should give you some information like the following:
On the right, under "Call Stack", you see alertme is called by testsecondcall