We use a bit of javascript that overwrites the setTimeout method for IE. This is because in some versions of IE the parameters do not get passed correctly (see here).
I have to load the modified setTimeout script first, because if I load it after the code that calls setTimeout is parsed (not run) then the modifed version does not get called.
What happens when the javascript engine parses files that have method calls to methods at the global scope? Do the mappings to the methods get created at parse time or when the code is executed?
EDIT
I have had a few answers to this question, which give other solutions to this problem, but the problem at hand is not my concern as I already have a solution for it. What I want to gain by this question is a better understanding of how javascript is parsed and run.
Methods are created at when the code is executed.
If the semantics of the code is correct interpreter is able to execute code.
While parsing nothing wasn't be executed.
File after parsing is executed singly one by one , before parsing the next.
Check this out:
We have two js files.
<script src ='1.js'></script>
<script src ='2.js'></script>
In second file we put declaration of setTimeout;
//file2
window.setTimeout = function(){};
In first file we'll checking for setTimeout being overridden
//file1
var f = function() { alert( setTimeout ); };
f();// alerts native setTimeout
setTimeout( f, 1000 ); // We use native settimeout, propably after one second file2 being loaded and executed and function `f` will be alerts the overriden setTimeout
If methods which I added were would be created during parsing. This would have access to it anywhere in the script in which it was created, even before its declaration.
so:
//somefile.js
setTimeout(); // we do not have access to function declared below, so while parsing this wasn't created.
window.setTimeout = function() { alert( 'whatever' ); }
EDIT #2
Fiddle #1 - http://jsfiddle.net/zEaL8/4/ - Allows you to set/reset a native function. To see how the redefinition and calling order works.
Fiddle #2 - http://jsfiddle.net/aKnjA/1/ -Demonstrates that the order of definition does not matter. Notice that the redefinition happens after the browser parses the call to the function.
EDIT
To answer your question: Javascript does not enforce any order of definition of functions. i.e. we can call a function defined afterwards in code. When the browser parses a line of code that calls a function that is defined afterwards, it does not have any clue as to where to find that function. This being the case, it is clear that binding happens only at run-time and not during initial parse. This in effect would mean that your redefinition of setTimeout is what will execute. The only thing to ensure is that the redefinition of setTimeout itself gets executed before any call to that is executed.
To ensure that the redefinition of your new setTimeout is processed first, you can place it in a script block as the first element inside the head node outside load, domReady etc.
i.e. Something like:
<html>
<head>
<script>
window.setTimeout = function() {
alert('new sT');
}
</script>
</head>
<body onload="setTimeout();"></body>
</html>
you can store original setTimeout in a global variable at the beginning of the code and then overload the setTimeot with a new function.
window.oldST = setTimeout;
window.setTimeout = function(funct,x) {
return oldST(funct,x);
}
so if these are the first lines of the js code you will have overloaded the setTimeout function with yours and set the old one in oldST.
Related
Can a function declared and attached to the global scope, but having jQuery-dependent code, always be depended on to work properly if it is only ever called from within a jQuery document-ready block?
e.g.:
<script src = "https://code.jquery.com/jquery-2.1.0.js"></sript>
<script>
function myFunc(){ alert( $('#someElem').text() ); }
$(function(){
myFunct();
})
</script>
In practice, I've seen this done a lot, with such functions being written to separate files entirely. I have never seen it fail, but part of me wonders whether or not this is truly safe.
I think at least partially this depends on whether document-ready waits for the completion of the javascript compilation phase of page-load. But are there other reasons this might fail?
Please disregard issues around polluting the global name-space, readability, and so forth. I am only concerned here with reliable execution.
It really can't fail, the $() function that looks up the element is only executed when the myFunc function is executed, and that function only executes once document.ready fires, so the element will be available at that time.
The global myFunc function will also always be available, as long it's defined before the document.ready code in the DOM.
In many cases it will even be available if defined after the document.ready code as DOMContentLoaded (and other such methods) is async and waits for the DOM to be ready, but there's no guarantee that all scripts will be loaded at that time, just that the elements in the DOM are available, so you should generally make sure that the myFunc function is defined before the $(function(){ ... }); code.
Such constructs are written only if myfunct() will be accessible from outside the scope of document.ready(). If other functions / events may also call it, it is better to move it out.
If it is only intended to be called once or on a particular event, it may be nested in the calling function body only.
One may even like to make the function calls fully contained structures like clorjures, and the likes. In that case too, the function would be nested inside another var declaration.
Other than this, there seems no other big difference.
Please add if I missed on anything!
Trying to figure out what this means in javascript.
(function(document) { ... } )(document);
It is isn't using jQuery, so is this just a javascript way of making this wait till document is ready to execute?
Thanks.
This won't wait for the document to be ready, this will execute the content of the function immediately. Putting the function definition in parenthesis makes it an expression, which returns a value being the function, making it directly executable. This pattern is called an Immediately-Invoked Function Expression (IIFE).
This is probably used in conjunction with a minifier like the Closure Compiler.
Inside the function, document is a local variable. This makes it possible for the minifier to reduce its name to a one or two character name.
Note also that all variables defined inside the function will be local : they won't leak in the global scope, which may be interesting if this is only part of the script.
This creates an anonymous function that takes a single argument, and immediately calls it passing document as the argument.
This:
function(document) { ... }
creates a function taking one paremeter.
This:
(function(document) { ... })
makes it (the code, not the function) a valid expression. See here.
This:
(function(document) { ... } )(document);
calls that function with document as a parameter.
It's a basic modularization pattern. In different environments you could've passed some other object instead of document, but nothing inside that function has to know bout it.
This is called self-executed function. It evaluates the anonymous function taking a parameter called document with that parameter passed in.
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?
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.
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:
By encapsulating the code in a closure anything explicitly declared inside is in the closure's scope, not the global scope. var loader is in the closure's scope.
By consuming the closure immediately it won't be stored in a variable in the global scope. Since it was declared anonymously it won't exist as a named function in the global scope.
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) {}
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.
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.
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.
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.
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:
If you define an anonymous function (using 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);.
The 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.
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.
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);
I want to periodically query a PHP script for new messages. To do so, I'm using the setInterval() function and AJAX.
$(document).ready(function(){
var queryInterval = 1000; /* How fast we query for new messages */
setInterval(getMessages(), queryInterval);
function getMessages() {
console.log("tick");
}
});
However, when I look at the Javascript console, I'm only seeing "tick" once. I've made sure that the console doesn't ignore any more logs of the same strings, so if the code was working properly it should show "tick" in the console every second.
Anyone know what could be going wrong here?
Change:
setInterval(getMessages(), queryInterval);
To:
setInterval(getMessages, queryInterval);
Actually, setInterval isn't running getMessages at all (not even once). setInterval expects a reference to a function, but you're executing the getMessages function immediately and passing its return value to setInterval (which is undefined). That's what the parens after getMessage do.
Pass a reference to setInterval like this:
setInterval(getMessages, queryInterval);
If this is the only place that getMessages is used, then you could also write it like this:
setInterval(function() {
console.log("tick");
}, queryInterval);
Remove the () after getMessage
This calls getMessages, not schedules it. Remove the parenthesis.
setInterval(getMessages(), queryInterval);
setInterval(getMessages, queryInterval);
Although others have already covered this ground above, both window.setTimeout() and window.setInterval() require function references. Your code provides, instead, the return value from a function invocation.
When you wish to call, or invoke, a JavaScript function, you write, as expected:
DoMyfunction();
The JavaScript engine will execute that function upon encountering that line.
However, what setTimeout() and setInterval() require, is a reference to the function object corresponding to your function. Which you obtain via the following, and similar means:
myFunc = DoMyFunction;
That line copies a reference to the function object corresponding to DoMyFunction() into a new variable. Which you can then pass to setInterval() and setTimeout(), viz:
discard = window.setTimeout(myFunc, 1000);
That line above will direct the JavaScript engine to execute your intended function (namely DoMyFunction()) once, after 1 second has elapsed, and:
discard = window.setInterval(myFunc, 1000);
will direct the JavaScript engine to execute your intended function repeatedly, once every second.
You could, of course, achieve the same effect, without using a new variable, simply as follows:
discard = window.setTimeout(DoMyFunction, 1000);
etc.
If, however, you make the mistake of using:
discard = window.setTimeout(DoMyFunction(), 1000);
what happens instead is that DoMyFunction() is executed, and any return parameter arising therefrom is then passed to the window.setTimeout() function. Since window.setTimeout() is expecting a function object reference to be passed here, and instead receives whatever your function returns (or undefined if your function returns nothing), then the internal checking performed by setTimeout() (and setInterval()) will reveal that it hasn't received a function object reference here, and simply abort silently.
A far more insidious bug, of course, could arise if DoMyFunction() actually does return a valid function object! If you've written DoMyFunction() to do this, then that function object will be passed to setTimeout() instead, and that function will be run! Of course, you could use this intentionally, and write your DoMyFunction() as a closure, returning the actual function you want setTimeout() to execute as a function object return parameter, and if you use that approach, then the form:
discard = window.setTimeout(DoMyFunction(), 1000);
will no longer be erroneous.
Remember, every JavaScript function you write in your code, when that code is parsed, is associated with a function object by the JavaScript engine. To execute the function, use:
DoMyFunction();
To reference the function object instead, use:
DoMyFunction;
Those () can make a huge amount of difference according to context, as a result of JavaScript taking this approach to differentiating between a function object reference and a function execution instruction.
Check your code line:
setInterval(getMessages(), queryInterval);
The setInterval function requires you to pass the reference to your callback function.
When you pass getMessages(), You are actually calling the function and passing its returning object to the setInterval function.
So just change your line to:
setInterval(getMessages, queryInterval);
and it will works fine!
In the answers to this question, we read that function f() {} defines the name locally, while [var] f = function() {} defines it globally. That makes perfect sense to me, but there's some strange behavior that's different between the two declarations.
I made an HTML page with the script
onload = function() {
alert("hello");
}
and it worked as expected. When I changed it to
function onload() {
alert("hello");
}
nothing happened. (Firefox still fired the event, but WebKit, Opera, and Internet Explorer didn't, although frankly I've no idea which is correct.)
In both cases (in all browsers), I could verify that both window.onload and onload were set to the function. In both cases, the global object this is set to the window, and I no matter how I write the declaration, the window object is receiving the property just fine.
What's going on here? Why does one declaration work differently from the other? Is this a quirk of the JavaScript language, the DOM, or the interaction between the two?
This two snippets declares a function in the current scope, named "onload". No binding is done.
function onload() { ... }
.
var onload = function() { ... }
This snippet assigns a function to a property/variable/field named "onload" on the current scope:
onload = function() { ... }
The reason why Firefox performed the binding and raised the onload event on the 1st snippet and the others didn't might be because the Firefox chrome (its user interface) itself is written and automated using JavaScript - that's why it's so flexible and easy to write extensions on it. Somehow, when you declared the locally-scoped onload function that way, Firefox "replaced" the window's (most likely the local context at the time) implementation of onload (at that time, an empty function or undefined), when the other browsers correctly "sandboxed" the declaration into another scope (say, global or something).
Many people are correctly pointing out the global / local difference between (UPDATE: Those answers have mostly been removed by their authors now)
var x = function() {
and
function x() {
But that doesn't actually answer your specific question as you aren't actually doing the first one of these.
The difference between the two in your example is:
// Adds a function to the onload event
onload = function() {
alert("hello");
}
Whereas
// Declares a new function called "onload"
function onload() {
alert("hello");
}
Here's what I think is going on, based on Tim Down's helpful comments and a brief discussion with Jonathan Penn:
When the JavaScript interpreter assigns to the window.onload property, it's talking to an object that the browser has given it. The setter that it invokes notices that the property is called onload, and so goes off to the rest of the browser and wires up the appropriate event. All of this is outside the scope of JavaScript — the script just sees that the property has been set.
When you write a declaration function onload() {}, the setter doesn't get called in quite the same way. Since the declaration causes an assignment to happen at parse time, not evaluation time, the script interpreter goes ahead and creates the variable without telling the browser; or else the window object isn't ready to receive events. Whatever it is, the browser doesn't get a chance to see the assignment like it does when you write onload = function() {}, which goes through the normal setter routine.
The simplest explanation:
function aaaaaaa(){
Can be used before it is declarated:
aaaaaaa();
function aaaaaaa(){
}
But this doesn't work:
aaaaaaa();
aaaaaaa=function(){
}
That's because in the third code, you are assigning aaaaaaa to an anonymous function, not declaring it as a function.
var onload = function() {
alert("hello");
}
Will declare it locally too.
I suggest you to read this very helpful article : http://kangax.github.io/nfe/
This generates an error:
foo();
var foo = function(){};
This doesn't:
foo();
function foo(){}
The second syntax is therefore nicer when you're using functions to modularize and organize your code, whereas the first syntax is nicer for the functions-as-data paradigm.