I have a JS file where I initialize this variable:
var totalSlideNumber = $(".background").length;
in file scope. I then try to print it to console on the next line:
var totalSlideNumber = $(".background").length;
console.log($(".background").length);
But this always prints 0. When I print the same variable in a function I get 3:
function parallaxScroll(evt) {
console.log($(".background").length);
...
Why are the values different from file scope to function scope?
Why are the values different from file scope to function scope?
It's not a question of "file scope" and "function scope", it's simply that the value is changing between the time you first execute the code and the time you next execute the code.
Specifically, this code:
$(".background")
When that selector queries the DOM the first time, it doesn't find anything. So the number of results is 0. When you execute it again later, it does file matches. So the number of results is 3 in this case.
It sounds like the first time you're executing the code is before the DOM structure has fully loaded. So the elements you're looking for simply don't exist yet. You can wait until the DOM structure is loaded and ready by using a document.ready handler:
$(document).ready(function () {
console.log($(".background").length);
});
Or, shorter:
$(function () {
console.log($(".background").length);
});
Related
Following is a sample code created based on the scenario. showData() function is defined inside a javascript load function. I wanted to call showData() from another file maybe on a button click. I know this will work if the showData is made global. It's not possible to make the function global, as in this scenario it's a dynamically generated code. Is there anyway in JS that allows to call such functions ?
// Not possible to change the structure of this file as its coming dynamically
window.addEventListener("load", function() {
showData(); // 1st time call
function showData() {
console.log('starting execution')
}
});
// Calling from another file
showData(); // 2nd time call - not possible
No.
The function is declared inside another function. Its scope is that function.
Unless you change that code to make it a global, it isn't accessible from outside the containing function at all.
If the structure of the code can't be changed, perhaps you could try attaching your function to the global window object, like:
window.addEventListener("load", function() {
// attached to window
window.showData = function() {
console.log('starting execution')
};
window.showData(); // 1st time call
});
// Calling from another file
window.showData();
But make sure the second call (from the other file) has a little bit of a delay (remember the eventListener has to be attached to the window first, before the function becomes available).
You could try:
// second call
setTimeout(function() {
window.showData();
}, 1000);
Why does this work,
function gettingValue() {
var holder = document.getElementById("testing").value;
document.getElementById("displayer").innerHTML = holder;
}
When the following doesn’t?
var holder = document.getElementById("testing").value;
function gettingValue(holder) {
document.getElementById("displayer").innerHTML = holder;
}
The language is Javascript, I was using Microsoft Edge and Opera browsers.
My guess is that the browser doesn’t perform code unless prompted. So var holder = document.getElementById(“testing”).value gets run in the first example because the function that contains it is called by a button.
When var holder = document.getElementById(“testing”).value is put inside a block of script with nothing ‘prompting’ it using the value holder returns undefined. Replaceing document.getElementById(“testing”) with a string “Blue” doesn’t work either. If a function calls holder the value returned is still undefined. So the browser did not create a varable.
I tried having the js document have;
function gettingValue(holder) {
document.getElementById("displayer").innerHTML = holder;
}
And passing the reference document.getElementById(“testing”).value to holder through the HTML document. It didn’t work, the function wasn’t even called because displayer stayed at Default instead of changing to undefined.
Oh experts of stackoverflow, please summarize how and when a browser reads/performs code.
//I realize this might be a 'discussion' which the tutorial said to avoid, if so I apologize. Tell me if this is so and I will not do it again.
Your guess is right - the variable definitions are run as soon as they are executed by the browser, so
var holder = document.getElementById("testing").value; is going to execute that instruction immediately, regardless whether the DOM structure is ready, since it's in outter-most scope. It all depends on where the code is placed in relation to the application entry point and runtime status.
This can obviously be correct, if that variable is defined in a correct place. Function body will only be executed when the containing function is called. It just 'sits' there, and until it is called, the only concern of the browser is if that code is syntactically correct(conforms to JavaScript specification syntax), i.e. can be parsed.
Your problem doesn't appear to have anything to do with when code is executed.
var holder = document.getElementById("testing").value;
The above defines a variable called holder. It is a global because it is outside of any function.
function gettingValue(holder) {
The function also defines a variable called holder by specifying it as an argument name. This variable is scoped to the function.
When you try to access the variable holder, you access the one in the nearest scope.
That's the argument to the function and not the global.
If you didn't mask it:
function gettingValue() {
Then you would be able to access the global.
Your question is very much about when code executes.
Let's look at each thing you tried. First
function gettingValue() {
var holder = document.getElementById("testing").value;
document.getElementById("displayer").innerHTML = holder;
}
That just tells the browser to create a function that is defined by that code in it. It really does not execute the contents of that function, just defines the function. In order for that function to get executed, you have to have some event or some other piece of code, that is executing, call that function. The call to that function, from some event (like a button press) or from other code, tells it to execute.
Now on your second attempt...
var holder = document.getElementById("testing").value;
function gettingValue(holder) {
document.getElementById("displayer").innerHTML = holder;
}
That first line of code is outside of any function definition and it will probably execute when the page loads. That holder variable DOES get created, and it has global scope, which means any function can access it. But, since you don't event have it inside a document_ready event handler, that "testing" control is probably still undefined (the page is not fully loaded when that statement executes) so you get undefined for the contents of "testing".
For your last example, it is hard to say what is going on without seeing the html that had those "testing" and "displayer" controls.
Bottom line, code gets executed when something calls it. When you load a page, any code that is outside of function declarations, executes and has global scope. Anything defined in a function gets executed when that function is called, either by an event or other code.
The issue with the code in the example is an issue with scope:
Your second example doesn't work as expected because you're referencing two different variables/pointers.
var holder = document.getElementById("testing").value;
function gettingValue(holder) {
document.getElementById("displayer").innerHTML = holder;
}
The following scope tree should explain this better:
GLOBAL SCOPE:
defined `holder` (through `var`)
gettingValue SCOPE
defined `holder` (as parameter)
Because you're defining holder as a parameter for gettingValue, you're no longer able to reference the global scope variable inside of gettingValue because they have the same name.
Specifying a parameter in a function definition is very similar to simply defining that variable within the function itself:
var holder = document.getElementById("testing").value;
function gettingValue(holder) {
document.getElementById("displayer").innerHTML = holder;
}
Is equivalent to:
var holder = document.getElementById("testing").value;
function gettingValue(firstParameter) {
var holder = firstParameter;
document.getElementById("displayer").innerHTML = holder;
}
Instead, you may have success doing one of the following:
function gettingValue(value) {
document.getElementById("displayer").innerHTML = value;
}
var holder = document.getElementById("testing").value;
gettingValue(holder);
OR
function gettingValue() {
var holder = document.getElementById("testing").value;
document.getElementById("displayer").innerHTML = holder;
}
gettingValue();
Notice in both examples above we have to call the function in order to execute it (using gettingValue()).
I hope this helps!
As a side note, Scotch.io has a great article that explains how scope works in JavaScript: https://scotch.io/tutorials/understanding-scope-in-javascript
Alright ; I had two misconceptions that were tripping me up.
I was assuming a local variable (used inside function) would be the same as a global variable if they had the same name. //Now that I realize that was the problem I remember reading about it.
I had thought document.getElementById(“blah”).value would be read from the ’s value every time it was used. This is not true, it is read only once when it is a global varable. As a local varable it is ‘read’ to whenever the function containing it is called.
I was blindsided by;
Global variables in javascript are read before the HTML document puts values into its elements. So that was why var holder = “Blue” returned “Blue” when var holder = document.getElementById(“testing”).value returned undefined. It was an order of operations thing. A value had not been put into the element yet. So my lesson is not to use document.getElement... in global variables.
Thank you all for your time and attention.
I have observed a strange behavior while learning jQuery and Javascript. When I call a variable that is defined inside the $(document).ready, from outside these tags it appears undefined, even when I define it as a global variable,
For example:
$(document).ready(function() {
myVar = "test";
});
alert(typeof(myVar));
//Results "undefined"
If I call the same variable inside the document.ready tags it works as expected
$(document).ready(function() {
myVar = "test";
alert(typeof(myVar));
//Results "String"
});
The result is same even after using window prefix.
$(document).ready(function() {
window.myVar = "test";
});
alert(typeof(window.myVar));
//Results "undefined"
I understand about the variable scopes but why even global variables aren't working this way. I am so confused.
The code inside the "ready" handler will not run until the DOM has been fully built. The code outside the handler will run as soon as it is encountered. Thus, your alert() runs before the code in the handler runs, so the outcome makes perfect sense: the global variable has not yet been initialized, so its value is undefined.
You can see the sequence of execution clearly by putting alert() (or, better, console.log()) calls inside the "ready" handler:
$(document).ready(function() {
console.log("In the 'ready' handler");
});
console.log("Outside the 'ready' handler");
When that runs, you'll see the "Outside" message logged first.
Because the alert() is executed before your document is perfectly ready.. You may try even by declaring the variable before $(document).ready() still it will return undefined..
The $(document).ready() gets fired after the page is fully loaded
When the script tag is fully loaded the alert gets executed.
So
Script tag is loaded => Execute alert
Continue loading page
Page completly loaded => fire $(document).ready
You var is getting set
The alert gets executed before your var is set
The other answers are correct but it is probably important to also note the $(document).ready(...) is also hiding your variable from the global scope. You could declare your variable then update it within the function
var myVar;
$(document).ready(function() {
myVar = "test";
});
console.log(myVar) // test
The execution plan it's like
//this statement shall fix the driver, not run it
$(document).ready(function() {//-->this it's an event handler waiting to be fired when content is fully loaded
myVar = "test";//-->myVar won't exists until this event is triggered
});
//this execute the alert function but myVar not exist yet
alert(typeof(myVar));
$(document).ready() is like to assign an event who will execute after the content is loaded, which means alert(myVar) will run before the lambda execution which was set as the content-loaded event. I hope you'll understand me.
I am trying to make a simple Chrome Extension.
At the top of the document, I have put var maxLengthVar;.
I have stored a number using the chrome.storage API. I am getting the value using:
chrome.storage.sync.get('maxLength', function (items) {
maxLengthVar = items.maxLength;
console.log(maxLengthVar);
});
The console.log displays the correct value (2). But when I try to use this variable, I get undefined:
console.log(maxLengthVar);
document.getElementById("textToChange").innerHTML = maxLengthVar;
Note: this code is directly below the first piece of code.
I expect to have the console log the number 2 and the div textToChange's content to change to 2, but, instead, I get undefined in the console and the div stays the same. Why is this?
From what I understand, I have a global variable because at the top of the document, I declared the variable, so what makes the document.getElementById... not read the variable?
Another thing is that even though the console.log's I said above are in the same order in the document, they appear in the console reversed (ie. I get undefined first and then 2.) I know because I added some text ('text' + maxLengthVar) to the console.log's. Why is this?
You need to read up on async methods.
Basically the get method is an async method. While this method is executing the remainder of your script will execute printing out undefined
chrome.storage.sync.get('maxLength', function (items) {
maxLengthVar = items.maxLength;
console.log(maxLengthVar);
});
// <- at this point the async GET method may not have finished executing
// but your code continues anyway
console.log(maxLengthVar);
document.getElementById("textToChange").innerHTML = maxLengthVar;
Your code can be re-written using callbacks
chrome.storage.sync.get('maxLength', function (items) {
maxLengthVar = items.maxLength;
document.getElementById("textToChange").innerHTML = maxLengthVar;
});
I recently started to learn Javascript and have prior experience in server side languages such as PHP. The issue I'm having is that I cannot use variables that are defined outside of a function inside the function. I always have to copy the variable into the function in order to get my code to work. I will post an example below.
var first = document.getElementById("first");
var second = document.getElementById("second");
function add () {
alert(Number(first.value) + Number(second.value));
}
Most likely the problem is that your script is being executed when the page is still being loaded, and before the "first" and "second" elements have been created.
Accessing the variables works fine. They just happen to be initialized to "undefined" at the time they are created. Moving the variables inside the function means that they aren't initialized until the function is called, which is after the page has been completely loaded.