Javascript - changing a global variable in document.ready? - javascript

I have a global variable numberOfMessages that I want to immediately set to a particular number according to what a call to a solidity contract brings back. The call is made in the document.ready function when the page is loaded. However, the variable isn't changed outside this function.
My code is basically like this:
var numberOfMessages = 0 // declared outside any function, so should be global
$(document).ready(function () {
Message.deployed().then(function (contractInstance) {
contractInstance.getNumberMessages.call().then(function (v) {
numberOfMessages = v
alert(numberOfMessages) // returns something other than 0
})
})
})
alert(numberOfMessages) // returns 0
How can I have a global variable that is set to what a function returns when the page is loaded?

Your final line is running outside of the promises' .then() async callback. This means the last line runs before document ready even fires and before your async call finishes.
Also, don't use alert() to test your code since prompts like that are usually blocking, meaning the halt code execution and can do weird things with async callbacks. Instead use console.log() and see the results in your browser's Javascript console (usually opened by hitting F12).

Try to remove
var numberOfMessages = 0
at first line. If you assign a value to a variable that has not been declared, it will automatically become a GLOBAL variable.

According to several other similar questions I could say declare your variable as window.numberOfMessages = 0.
#3 window.a = 0;
This creates a property on the global object explicitly, using the
window global that refers to the global object (on browsers; some
non-browser environments have an equivalent global variable, such as
global on NodeJS). As it's a normal property, you can delete it.
This property is enumerable, on IE8 and earlier, and on every other
browser I've tried.
Above classification has posted by here and gives you an explanation of what is a global scope variable and global explicitly variable.
window.numberOfMessages = 0 // This creates a property on the global object explicitly
$(document).ready(function() {
Message.deployed().then(function(contractInstance) {
contractInstance.getNumberMessages.call().then(function(v) {
window.numberOfMessages= v
console.log(window.numberOfMessages) // returns something other than 0
})
})
})
console.log(window.numberOfMessages) // returns 0
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

Related

Why does console log show variable that is already defined

Curios why this happens
if(typeof TEST === "undefined") {
var TEST = true;
console.log(TEST);
}
if i place in console , it returns true
if i add again in console , then no console log is shown , which is exactly how I would assume it should work.
When i place in interval , why does it continue to log the variable even though its defined ?
setInterval(function(){
if(typeof TEST === "undefined") {
var TEST = true;
console.log(TEST);
}
}, 1000);
How can you make it stop showing the log after its defined ? Without clearing the interval
If you put it in the console then var creates a variable in the top level scope. It is undefined, so you assign true to it. If you put it in the console again then it is true from the previous time.
If you put it inside a function, then it is scoped to the function, so every time you run the function you create a new scope and a new var TEST.
Declare the variable in a scope outside the function instead.
In the first case, you're testing the global variable. Once it's defined, it stays defined.
In the second case, the variable is local to the callback function. Every time the function is called, it's a new variable that isn't defined yet.
If you remove the var declaration in the setInterval() version it will assign to the global variable, and it will stay defined.
The simplest solution is probably to use let or const instead of var. If of course you have the possibility.

Closure of function defined as an argument

Disclaimer: This question is purely curiosity driven and has to do a lot with how the javascript works.
I understand why the following code works. Due to closures, foo has access to the scope where a resides. This makes sense.
var a = 10
var foo = function(){
console.log(a);
}
setTimeout(foo,1000)
However, i wonder why the following also works (explained right after).
var a = 10
setTimeout(function(){
console.log(a);
},1000)
The function is defined in the argument of the function receiving it and essentially was never a closure to the scope that contains a. We know that when a function receives an argument, it creates a local variable for that argument so for example
var outerVar="5"
var bar = function(a){
//implicitly, var a = outerVar happens here
console.log(a)
}
bar(something);
So following that logic, the function passed to setTimeout couldnt have access to a and yet it does.
Im suspecting that when a function is defined in the argument space what happens is, it realy is defined before being assigned as an argument but have no proof of that. Any pointers highly appreciated.
Thanks a bunch.
It's not exactly closure, but it's close.
Strictly speaking, closure is when a variable's scope ends, but is still enclosed in an inner function that still lives on:
function createTimer() {
let counter = 0;
return function() {
return counter++;
}
}
const timer = createTimer(); // function() { ... }
console.log(timer(), timer(), timer()); // 0, 1, 2
The function in which counter is defined has returned, the scope ended, and under normal circumstances, counter should have died and garbage collected. But the inner function returned from createTimer() still has a reference to it, from the enclosed scope, that is a closure.
In JavaScript, every function has access to all of the scopes of all of its ancestors, this is what you're seeing here.
The function passed to setTimeout() has access to a because a is defined in the scope around it.
When you look at a javascript code and see how it works, the best way according to me is first understand the javascript engine how it works.
First it traverses the code and assigns all the variables to the scope and further more in the second trace it assigns the values based on the scopes.
So in your first code,
The engine first traverses and assigns
var a to global scope,
var foo as global scope,
Then when setTimeout runs it calls foo function and logs the value of a as that of the global a as it doesnt have any local “a” so checks the lexical scoping.
In your second code,
Var a is again global scoped
and no other declaration this time.
In second traverse it assigns the value 10 to a and interprets the settimeout and prints the value
In your third code,
Same as the second one except the fact that instead what “foo” was giving to the settimeout function, you wrote your callback function then n there itself.
By the time l it executed the setTimeout,
Each of your codes have the value for “a” in the global scope that they are accessing.

javascript variable

do we have to declare js variable like this:
var x=5;
or just simple like this
x=5;
what is the differences?... will it effect the functionality of the variable?...
variable_name = 5 would always put the variable_name into the global object (which is window in a browser)
If you are in the global context (= not a function context) the two statements are basically the same. But if you are in a function context, var makes sure that this variable is only declared within the current context.
So for instance:
function foobar() {
bar = 55;
}
foobar();
window.bar === 55 // true
Better:
function foobar() {
var bar = 55;
}
window.bar === 55 // false
Conclusion: always use var within the context of a function. This avoids clobbering / overriding the global object with variables.
The var keyword limits the scope of the variable to the current function. Leaving it off makes a global. Globals are bad and should be avoided as they are a key source of race conditions and scripts interfering with each other.
x=5 means this variable (after execution) will become global and can be accessed by all other parts in your code(and also by other javascripts).
while var x=5 will be familiar only to the block which it was declared on, (and it's descendants)
Note that although x=5 will be global, it will become global only when this line is execute!
So if you place this inside a function, it will become global only after that function is called (for the first time).
It makes no difference - with the second one (x=5;) the variable is automatically declared if it does not yet exist.
I always use the first option however.

How to create Semaphore between HTML elements loaded async

I have in an HTML page, an element that appears several times, and running the same JS.
Problem is, I want it to do a specific function only if it was the first one to run it (his siblings never ran it - YET).
I need semaphore to sync between them.
I am unable to know how to declare a variable and to do semaphore in this way in JS.
There are lots of approaches.
You need to put a flag somewhere. In the absence of anything else, you can put it on window, but use a name that's unlikely to conflict with anything else.
Then the JavaScript is quite straightforward:
if (!window.myUniqueNameFlag) {
window.myUniqueNameFlag = true;
// Do your processing
}
But again, putting things on window is not ideal if you can avoid it, although it's very common practice. (Any variable you declare at global scope with var¹ is a property of window, as is any function you declare at global scope.)
If your function is already declared at global scope (and therefore already occupying a global identifer / window property), you can do this to avoid creating a second identifer. Instead of:
function foo() {
// ...your processing...
}
Do this:
var foo = (function() {
var flag = false;
function foo() {
if (!flag) {
flag = true;
// ...your processing...
}
}
return foo;
})();
That looks complicated, but it's not really: It defines and immediately invokes an anonymous function, within which it defines a variable and a nested function, then it returns the nested function's reference and assigns it to the foo variable. You can call foo and you'll get the nested function. The nested function has an enduring reference to the flag variable because it's a closure over the variable, but no one else can see it. It's completely private.
A third option is to just use a flag on the function object itself:
function foo() {
if (!foo.flag) {
foo.flag = true;
// ...do your processing...
}
}
Functions are just objects with the ability to be called, so you can add properties to them.
¹ Variables declared at global scope with let or const are globals, but do not become properties of window.

Difference between JavaScript function declarations?

Why does calling my JavaScript function throw an error when I call it like this
wysiwyg2();
var wysiwyg2 = function()
{
alert(1);
}
but work when I do this?
wysiwyg2();
function wysiwyg2 ()
{
alert(1);
}
You need to define your function variable first, i.e.
var wysiwyg2 = function()
{
alert(1);
}
wysiwyg2();
For a good explanation of the difference, see Why can I use a function before it’s defined in Javascript?
In the first snippet, you're trying to invoke a variable before the variable is defined.
You'd get the same problem from the following code:
test.toString();
var test = new Date;
In the second snippet, you're declaring the function without assigning it to a variable, and this results in a global declaration that is usable in earlier code.
You can think of your javascript as though it's evaluated in two passes. The first pass builds all the objects and names (and remember: functions are objects), and places them "in scope", so to speak. It's kind of like a compilation step. Then the second pass executes the code.
So your second sample works because the first pass built and "scoped" the function before execution. The first sample does not work because the function object is created as part of a variable assignment, and so it's not in scope yet when you try to call it.
You mention another situation in the comments, where the function call and definition are separated into two script blocks. That doesn't work because the engine completes both steps of one block before moving on to the next, and you tried to call the function in a block that is executed before the block where it's defined. You can call function across script blocks, but not until they are defined.
In the first one, you're declaring a function and assigning it to a variable. Thus you won't be able to call it through that variable until it's actually assigned to it.
In the second, you're declaring a named function. And can call that function from wherever (as long as it's in scope).
When entering a new execution context (which is either a function call or global code), JavaScript first goes through a variable instantiation phase during which all variable declarations and function declarations within the global code or function body are examined and create as properties of the current variable object, which is effectively a collection of all the objects that are in the current scope. In particular, any function declaration such as
function wysiwyg2 ()
{
alert(1);
}
... is fully created during this phase, while any variable declaration such as
var a = 2;
... only leads to the creation of a variable called a with a value of undefined during this phase. This is also true of a variable declaration with an assignment to a function expression, such as
var wysiwyg2 = function()
{
alert(1);
}
Only the variable instantiation takes place at this point. Once this phase is complete the rest of the code (including variable assignment) is executed sequentially.

Categories

Resources