When/Why does a Browser Implement Code - javascript

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.

Related

Differences when using functions for casper.evaluate

I'm using PhantomJS v2.0 and CasperJS 1.1.0-beta3. I want to query a specific part inside the page DOM.
Here the code that did not work:
function myfunc()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
}
var del=this.evaluate(myfunc());
this.echo("value: " + del);
And here the code that did work:
var del=this.evaluate(function()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
});
this.echo("value: " + del);
It seems to be the same, but it works different, I don't understand.
And here a code that did also work:
function myfunc()
{
return document.querySelector('span[style="color:#50aa50;"]').innerText;
}
var del=this.evaluate(myfunc);
this.echo("value: " + del);
The difference here, I call the myfunc without the '()'.
Can anyone explain the reason?
The problem is this:
var text = this.evaluate(myfunc());
Functions in JavaScript are first class citizen. You can pass them into other functions. But that's not what you are doing here. You call the function and pass the result into evaluate, but the result is not a function.
Also casper.evaluate() is the page context, and only the page context has access to the document. When you call the function (with ()) essentially before executing casper.evaluate(), you erroneously try to access the document, when it is not possible.
The difference to casper.evaluate(function(){...}); is that the anonymous function is defined and passed into the evaluate() function.
There are cases where a function should be called instead of passed. For example when currying is done, but this is not applicable to casper.evaluate(), because it is sandboxed and the function that is finally run in casper.evaluate() cannot use variables from outside. It must be self contained. So the following code will also not work:
function myFunc2(a){
return function(){
// a is from outer scope so it will be inaccessible in `evaluate`
return a;
};
}
casper.echo(casper.evaluate(myFunc2("asd"))); // null
You should use
var text = this.evaluate(myfunc);
to pass a previously defined function to run in the page context.
It's also not a good idea to use reserved keywords like del as variable names.

Can't use variables outside of function in javascript

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.

How can I make variables so that I don't have to repeat myself in future functions

WARNING!! I AM A NOVICE THROUGH AND THROUGH
Alright, so I know there have been a lot questions about Global variables, and I think that's what I'm looking for, but, not exactly. Lately I've been needing to call upon the same lines of code several times. document.getElementById("example").style or similar to little things like that but I need to continuously repeat.
My question is how do I make it so that I make one variable, outside of the function, to save time writing these lines?
What I've been seeing is to simply write it outside like this var inferno = document.getElementById("inferno"); but this is far from working.
This is my code right now, it's simple because I was just using it as a test, but can anyone help me?
var inferno = document.getElementById("inferno");
function infernoClick () {
inferno.style.backgroundColor="red";
}
You have the right idea. Note, though, that the variable doesn't have to be global. It just has to be where all of the code that wants to use it can use it.
For example, this creates a global:
<script>
var inferno = document.getElementById("inferno");
function infernoClick () {
inferno.style.backgroundColor="red";
}
function somethingElse () {
inferno.style.color="green";
}
</script>
(Note that this needs to be after the markup creating the inferno element.)
The problem with globals is that they can conflict with each other, and in fact the global "namespace" is really, really crowded already.
You can avoid that by wrapping up the code that needs inferno in a scoping function, like this:
<script>
(function() {
var inferno = document.getElementById("inferno");
function infernoClick () {
inferno.style.backgroundColor="red";
}
function somethingElse () {
inferno.style.color="green";
}
})();
</script>
That code creates an anonymous function and then calls it immediately, running the code inside.
Now inferno is "global" to the functions that need it, but isn't actually a global.
Let's take a further example:
<script>
(function() {
var outer = 42;
function doSomethingCool() {
var inner = 67;
document.getElementById("someElement").onclick = function() {
alert("inner = " + inner + ", outer = " + outer);
};
}
// Can't use `inner` here, but can use `outer`
alert("outer = " + outer);
doSomethingCool();
})();
</script>
That code wraps everything in a scoping function, and the outer variable is accessible everywhere within that scoping function. It also has a function, doSomethingCool, which has a variable called inner. inner is only accessible within doSomethingCool. Look at what doSomethingCool does: It hooks up an event handler for when someElement is clicked. It doesn't call the function, it just hooks it up.
The really cool thing is that later, when someone clicks the element, that function has access to that inner variable.
And in fact, that's true for arguments you pass into the function as well. One last example:
<input type="button" id="element1" value="One">
<input type="button" id="element2" value="Two">
<script>
(function() {
function hookItUp(id, msg) {
document.getElementById(id).onclick = function() {
alert(msg);
};
}
hookItUp("element1", "This message is for element1");
hookItUp("element2", "And this one is for element2");
})();
</script>
There, we have this function that accepts a couple of arguments, and we call it twice: Once to hook up click on element1, and again to hook up click on element2.
The really cool thing here is that even though the clicks happen much later, after the calls to hookItUp have long-since returned, the functions created when we called hookItUp still have access to the arguments we passed to it — when we click element1, we get "This message is for element1", and when we click element2, we get "And this one is for element2."
These are called closures. You can read more about them on my blog: Closures are not complicated
That'll work, but only if the declaration appears after the point in the DOM where the element actually appears. Try moving your <script> to the very end of the <body>.
Another thing you can do is use the window "load" event to make sure the whole DOM has been seen before your code runs.
for example
var myGlobalVars = {"inferno":null,"othervar":null}; // globals in their own scope
function clickMe(varName,color) { // generic function
myGlobalVars[varName].style.backgroundColor=color;
}
window.onload=function() {
// initialise after the objects are available
for (var o in myGlobalVars) myGlobalVars[o]=document.getElementById(o);
// execute
clickMe("inferno","red");
}
.
.
T.J. Crowder gave a beautiful answer about scoping; just to add on that you can also use an immediately-invoked function expression to create a module with your UI elements, i.e.
var UI = (function() {
...
return {
inferno: document.getElementById("inferno");
};
})();
...
UI.inferno.style = ...;

Javascript Variable Not Changed Outside of Function Scope

I have the following function:
function loginStudent() {
var advisorKEY = "<dtml-var expr="py_get_alias()">";
var studentKEY = "<dtml-var SID>";
var URL = "py_logging_sessionOpen?AdvisorKEY=" + advisorKEY + "&StudentKEY=" + studentKEY;
key = "";
$j.get(URL, function(data) {
key = data;
});
alert(key);
}
The py_loggin_sessionOpen is just a python script running on my server.
It returns a single string. I need the response of that script to determine the next action. The script returns the value perfectly, and I can easily check the value by putting an alert within the function(data) in get.
My main question is: how to get the key value to be changed outside the scope of function(data)?
I assumed because I defined it externally it would act as a global variable.
Moving it outside loginStudent() does not solve the problem either.
Any ideas?
$j.get() is going to be an asynchronous call. That means it fires, and the rest of the execution continues. Anything that relies on that call needs to be done in the callback, like so:
$j.get(URL, function(data) {
key = data;
alert(key);
} );
If everything else is good, you'll see the value you expect.
The problem with your code is that $j.get executes asynchronously. That's the reason you pass a callback to it.
If you wish to write asynchronous code synchronously then you should read this answer: https://stackoverflow.com/a/14809354/783743
Edit: It seems that you have created a global variable called key by not declaring it with var. Hence it should be visible in other functions as long as they are called after the callback.
Would you care to provide us these other functions?

does var onload mean that it should run when page is loaded

// test.js //
var testObj = {};
testObj.init = function(){
console.log('google');
}
var onload = testObj.init;
/// what does it mean, does it mean it gets executed when script loaded or what, I just can't understand it as it is not looging into console anything under Google Chrome plugin...
Think of it like giving your dog 2 names:
var spot = new Dog();
var comeHereSpot = function () { return spot; }
var comeHereBoy = comeHereSpot;
Whether you call comeHereSpot or comeHereBoy the same dog will come running.
It just means that your variable onload now points to
function(){
console.log('google');
}
onload is just the name of a local variable here.
It means that variable onload is a reference to the function testObj.init. onload() will execute the function and output 'google' to the console.
No, it only means that you assign it to a variable named onload.
Depending on the scope of the code it might actually work, if the variable name collides with the onload property of the window object. In that case a variable would not be created, but it would use the existing property instead. You should not rely on this behaviour though, you should always specify it as a property of the object:
window.onload = testObj.init;
In your code, onload is simply the name of a local variable. The var keyword declares local variables. You're setting the value of onload to testObj.init, which is a function that prints 'google' to the console.
To make it run the function on page load, set window.onload to the value of the function.
window.onload = testObj.init;
Or, better yet, use event handlers to attach an "onload" event to the window object. (To make this easier, use a JavaScript library such as jQuery, but I recommend you first learn how it all works.)
Nothing is logged because you are simply setting onload to be a pointer to the function testObj.init which only gets the function's code. To actually run it, you must call testObj.init().
More about onload…
onload is a property of an HTML element that can be set to run javascript. For example:
<html>…
… <body onload="testObj.init()"> …
…</html>
This means that when the "body" element is loaded, the function testObj.init() is run.
The "onload" property can also be attatched by javascript, as in:
window.onload=myFunction();

Categories