What is the scope of a JavaScript function? [duplicate] - javascript

I'm not quite sure what goes on between <script> tags. For example, the following gives a reference error and type error in Chrome:
<html>
<head>
<script type="text/javascript">
T.prototype.test = function() {
document.write("a");
}
</script>
<script type="text/javascript">
function T() {}
var v = new T();
v.test();
</script>
</head>
<body>
</body>
</html>
But this works:
<html>
<head>
<script type="text/javascript">
</script>
<script type="text/javascript">
T.prototype.test = function() {
document.write("a");
}
function T() {}
var v = new T();
v.test();
</script>
</head>
<body>
</body>
</html>

The upper script is executed first in the first example, so it doesn't know about T yet, hence the error.
In the second example, T is well defined and known anywhere as soon as the script tag is executed. This is due to function declarations being hoisted to the top, no matter what the order is, they are always available. Function declaration hoisting is more deeply explained here
The second example after hoisting is applied:
var v,
T = function(){}; /* using comma like this is short-hand for: var v; var T = function(){}; */
T.prototype.test = function() {
document.write("a");
};
v = new T();
v.test();

They are each parsed in the global context, but in order. The entire first script tag is parsed and executed before the second one is considered. As part of parsing a script, function declarations are recognized ahead of time, which is why the second one works while the first one doesn't.

Related

Socket JS not works inside onload method

I have this js piece which I use for django channels:
var chatSocketSender1 = new WebSocket(
'ws://' + window.location.host + '/ws/my_socket1/'
)
function send() {
var msg = "some message"
var receiver_id = 111
window['chatSocketSender1'].send( JSON.stringify({
'msg': msg,
'receiver_id': receiver_id
}) )
}
document.querySelector('#send_button').onclick = function() {
send();
}
The problem is that this js code only works if I put that after latest element of HTML:
<head>
...
</head>
<body>
// whole html content here
<script>
// js piece here
</script>
</body>
But if I use jquery's on load method like:
<head>
<script>
$(window).on('load', function () {
// js piece here
});
</script>
</head>
<body>
// whole html content here
</body>
Then it gives: Uncaught TypeError: window[("chatSocketSender1")] is undefined
Any suggestion please, why this not works with "onload" ?
The reason your code doesn't work is because in your first code var chatSocketSender1 creates a "global" variable (that's defined at the window level) that you later reference as window("chatSocketSender1"), but in the second code, var chatSocketSender1 is scoped to the anonymous event handler function, so is not available as window("chatSocketSender1").
Put another way:
<script>
var x = 1;
function foo() {
console.log(x)
}
</script>
works fine, but
<script>
function foo() {
var x = 1;
}
foo();
console.log(x);
</script>
will give an undefined variable error as x only exists inside foo. This isn't exactly what you've done, but is essentially the same concept.
Now, if your code was:
chatSocketSender1.send(
then it would have worked fine as your variable chatSocketSender1 is defined within the function() { onload event callback.
or instead of
var chatSocketSender1 =
you could do
window.chatSocketSender1 =
to define the variable globally, or you could:
<script>
var chatSocketSender1 = new WebSocket(...
function send() { ... }
$(window).on('load', function () {
document.querySelector('#send_button').onclick = ...
as you generally only need the event binding within the onload.

JavaScript Global Var Hoisting Issue

Here is my basic issue...
<script>
var window.my_Global = false;
</script>
<script>
if(my_Global){...} //my_Global here is undefined, not false??
</script>
I know there must be a simple solution but I'm pretty stuck...
Remove var:
window.my_Global = false;
You don't need the var statement to set properties of an object. In fact, that's invalid syntax:
<script>
window.my_Global = true;
</script>
<script>
console.log(my_Global);
if(my_Global){
alert("Hello world!");
}
</script>

Javascript function not executing when another function is above it

So, the function "txtLoad()" will not execute while "txtFunc()" is being called by an onLoad function.
<!DOCTYPE html>
<html>
<head>
<title>Page</title>
</head>
<body>
<textarea id="Text" rows="20" cols="70"></textarea>
<script>
function txtFunc(){
var q=1;
}
function txtLoad() {
document.getElementById("Text").innerHTML = "Hello";
}
onload=function(){
txtLoad()
}
onload=function(){
txtFunc()
}
</script>
</body>
</html>
The JavaScript engine says there is nothing wrong with the code inside the "script" element. Does anyone know why the function isn't executing?
your second onload= replaced the function that calls txtLoad, if you want to run both:
onload = function () {
txtLoad();
txtFunc();
};
Also there seems to be extra "}" after the txtFunc.
How can two functions be defined to the onload. For eg:
var x = 1
var x = 2
What do you think the value of x is going to be? Obviously 2.
You are overwriting the onload. Its only going to execute the stuff which you assigned at last.
You could do this to achieve what you want.
onload = init()
function init() {
textLoad();
textFunc();
}
simply because the first onload was overwritten by the las onload.
function txtFunc(){
var q=1;
}
function txtLoad() {
document.getElementById("Text").innerHTML = "Hello";
}
onload=test();
function test()
{
txtLoad();
txtFunc();
}

Why JavaScript function visibility depends on declaration in the same or different script block in HTML

If I implement the following JavaScript code block in HTML markup:
<script type="text/javascript">
function MyFunc() {
alert(1);
}
var f1 = MyFunc;
</script>
<script type="text/javascript">
function MyFunc() {
alert(2)
}
</script>
<script type="text/javascript">
f1();
</script>
I get an alert message '1'.
However, if I use the following code:
<script type="text/javascript">
function MyFunc() {
alert(1);
}
var f1 = MyFunc;
function MyFunc() {
alert(2)
}
</script>
<script type="text/javascript">
</script>
<script type="text/javascript">
f1();
</script>
I get '2'. Why?
Tested in IE10, latest FF, Chrome.
This is caused by hoisting. var and function declarations are hoisted to the top of the script block they are in.
This means that your first script essentially becomes:
var f1;
function MyFunc() {
alert(1);
}
f1 = MyFunc;
// new script block
function MyFunc() {
alert(2)
}
// new script block
f1(); // alert 1
Meanwhile, your second script becomes:
var f1;
function MyFunc() {
alert(1);
}
function MyFunc() { // overwrite previous MyFunc
alert(2)
}
f1 = MyFunc;
// new script block
f1(); // alert 2
I hope this makes sense - just in general avoid overwriting functions XD
Each script element is parsed and executed in order. In the first case, the assignment to f1 is made before the second declaration is processed.
In the second case, both declarations are parsed before the assignment is made (because declarations are processed before any code is executed), so the second declaration replaces the first before the assignment to f1.
I hope I don't confuse anybody, but, I suspect the answer has something to do with scopes.
Here is my argument:
For the 1st case:
<script type="text/javascript">
function MyFunc() {
alert(1);
}
var f1 = MyFunc;
window.foo1 = MyFunc;
</script>
<script type="text/javascript">
function MyFunc() {
alert(2)
}
window.foo2 = MyFunc;
</script>
<script type="text/javascript">
f1();
alert(window.foo2 === window.foo1);
</script>
The second alert will issue a false.
Now the 2nd case.
<script type="text/javascript">
function MyFunc() {
alert(1);
}
var f1 = MyFunc;
window.foo1 = f1;
function MyFunc() {
alert(2)
}
window.foo2 = MyFunc;
</script>
<script type="text/javascript">
</script>
<script type="text/javascript">
f1();
alert(window.foo1 === window.foo2);
</script>
The second alert will issue a true.
It kind of shows that (for 1st case) MyFunc is redefined and is a totally different "object" when the 2nd script block is processed. f1 holds a reference to the first "object" in the first script block. Hence f1() alerts 1.
For the first part with alert message 1 the declaration var f1 = MyFunc; becomes similar to a local wrt different <script> blocks.Hence the <script> block in which var f1 is defined it performs the function contained in that block.
For the second part with alert message 2 , 1st MyFunc() is overwritten by the second.

load javascript after loading the page

I have read a lot of topics and tried a lot of stuff but I can't get what I want.
I just moved my js code at the end of the page and now I get some errors.
This is how my page looks like:
<html>
<head>
bla bla
</head>
<body>
bla bla
<div class="advertising">
<script type="text/javascript" defer="defer">
window.onload = adsense();
</script>
<script type="text/javascript" src="http://pagead2.googlesyndication.com/pagead/show_ads.js">
</script>
</div>
<script language="javascript" type="text/javascript" src="fonctions.js"></script>
</body>
</html>
In fonctions.js I have my google adsense code:
function adsense(){
<!--
google_ad_client = "pub-xxxxx";
/* 120x600, date de création 11/06/11 */
google_ad_slot = "xxxxx";
google_ad_width = 120;
google_ad_height = 600;
//-->
}
The idea was to have the same code for adsense at only one place but I can't get it to load after the file fonctions.js
I tried defer="defer", window.onload ...
Any ideas?
Thanks
I get this error in Firebug:
Error : adsense is not defined
PS: I would like to avoid to use Jquery (to avoid making pages too big)
UPDATE:
<script type="text/javascript" defer="defer">
(function() { // 'sandbox' javascript pattern to prevent clobbering
// global namespace
var executeProxy = function() {
if (typeof adsense === 'function') { // adsense is configured
adsense();
} else { // adsense is not configured;
// therefore, try again later
setTimeout(executeProxy, 50);
}
};
executeProxy();
}());
</script>
<script language="javascript" type="text/javascript" src="fonctions.js"></script>
in fonctions.js if I put the following code, the "ok" is displayed:
function adsense(){
alert ("ok");
}
However if I have this code, the ad is not displayed:
function adsense(){
google_ad_client = "pub-xx";
/* 120x600, date de création 16/04/11 */
google_ad_slot = "xxx";
google_ad_width = 120;
google_ad_height = 600;
}
My guess is that it's a Google issue... The code cannot be loaded in this way...?
If I put the adsense code in the page (below the call - where you do alert('here'); ) it is well displayed... So my adsense code is correct
UPDATE:
I have finally changed the solution, I've put the code in a .html file and I include it using php. So it's not in my js file anymore.
Thanks for your help anyway.
window.onload expects a function callback; however, you are executing adsense with adsense(), and adsense doesn't return a function; therefore, window.onload will discard that. Change to:
window.onload = adsense;
UPDATE
The above answer should be discarded, but I'm leaving it up so that people can know that window.onload expects a function callback :)
Keep in mind that defer on the script element will instruct the browser to wait until the page has been loaded to execute the script; however, your fonctions.js is in the src attribute of your last script tag; therefore, your deferred script will most likely execute before adsense has been defined, because the browser will make an http request to retrieve your script. This will allow deferred scripts to continue executing while adsense is not defined. Try this in place of your original deferred script:
<script type="text/javascript" defer="defer">
(function() { // 'sandbox' javascript pattern to prevent clobbering
// global namespace
var executeProxy = function() {
if (typeof adsense === 'function') { // adsense is configured
adsense();
} else { // adsense is not configured;
// therefore, try again later
setTimeout(executeProxy, 50);
}
};
executeProxy();
}());
</script>
UPDATE
I forgot that script defer is not supported in anything outside of IE. Therefore, the deferring issue should not be at play here; however, I tested the following code in FF and Chrome, and it works:
<script type="text/javascript" defer="defer">
(function() { // 'sandbox' javascript pattern to prevent clobbering
// global namespace
var executeProxy = function() {
if (typeof adsense === 'function') { // adsense is configured
adsense();
} else { // adsense is not configured;
// therefore, try again later
setTimeout(executeProxy, 50);
}
};
executeProxy();
}());
</script>
<script type="text/javascript">
function adsense() {
alert('here');
}
</script>
window.onload = adsense(); calls adsense() immediately and assigns its return value to onload.

Categories

Resources