Value of variable is always undefined [duplicate] - javascript

alert(myVar1);
return false;
var myVar1;
Above code throws error in IE, FF and Opera stating that return statement has to come in the function. But it works (shows undefined) in Safari and Chrome.
The above code has been written in global scope. Outside all the functions.
Any reason?

In JavaScript variables are moved to the top of script and then run. So when you run it will do
var myVar1;
alert(myVar1);
return false;
This is because JavaScript doesn't really have a true sense of lexical scoping. This is why it's considered best practice to have all your variables declared at the top of the area they will be used to prevent hoisting causing a problem. JSLint will moan about this.
This is a good article that explains it: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
The return is invalid. If you want to do a true hoisting example (taken from the link above) do
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
This will alert 10
Below is my understanding and I have read it somewhere but can't find all the sources that I read so am open to correction.
This Alerts thanks to the differences in the JavaScript JIT. TraceMonkey(http://ejohn.org/blog/tracemonkey/) I believe will take the JavaScript and do a quick static analysis and then do JIT and then try to run it. If that fails then obviously nothing works.
V8 doesn't do the static analysis and moves to the JIT then runs so something. It's more akin to Python. If you run the script in the Developer console (ctrl+shift+j in Windows) in Chrome it will throw an error but also run to give you the alert.

Sometimes hoisting is explained in a way which may give wrong impression, i.e. the variables and functions are hoisted by JavaScript engine as if they were physically moved on top, which is not actually right, as demonstrated by the code below:
console.log(a);
var a = 'Hello World!';
What we see on console is undefined, not 'Hello World', so we got the behavior of the following code
var a;
console.log(a);
a = 'Hello World!';
not the behavior of
var a = 'Hello World!';
console.log(a);
which you may get the impression from the variables and functions declaration being moved to top statement.
But JavaScript is not actually moving your code anywhere. You need to understand execution context in JavaScript. It has two phases creation phase and execution phase. In creation phase memory space is created for these variables and functions, and people seem to confuse this step with hoisting. JavaScript is actually not moving your code anywhere, what happens is JavaScript has created memory space for all your code i.e. variables and functions, functions can be placed fully in memory but in case of variables the assignments are processed in execution phase of the execution context. So when you do var a = 'Hello World!', JavaScript engine knows the value of a when it starts executing it in execution phase of execution context, so it puts a placeholder undefined, and all variables are initially set to undefined in JavaScript. So it is not good to rely on hoisting and see undefined. So it is always good to declare variables and functions on top of your code.

Section 12.9 (page 75) of ECMA-262 edition 3 states:
An ECMAScript program is considered syntactically incorrect if it contains a return statement that is not within a FunctionBody.
That is, a return outside of a function is a syntax error. If a syntax error occurs, no code is run. Think about your example as if you had written:
alert(myVar1);
return false;
syntax error))))))))))))))))));
In addition, section 16 (page 157) states:
An implementation may treat any instance of the following kinds of runtime errors as a syntax error and therefore
report it early:
Improper uses of return, break, and continue.
Firefox's engine et. al. (i.e. those JavaScript implementations which allow return in the global scope) may be conforming, assuming the following clause (in the same section) allows for implementation definition of return in the global scope:
An implementation shall report all errors as specified, except for the following:
An implementation may provide additional types, values, objects, properties, and functions beyond those described in this specification. This may cause constructs (such as looking up a variable in the global scope) to have implementation-defined behaviour instead of throwing an error (such as ReferenceError).

This code makes little sense:
The var myVar1 will never be ran.
The return false; will not return a thing since you're not in a function
Opera, IE and FF are right to throw an error because this code is really not valid since you're not able to return unless you are in a function.
If it works in Safari and Chrome it must be because the javascript engine they use is ready to handle buggy code. My guess would be that they see the "return" and drop or replace it with some kind of break.
More information about functions: http://www.w3schools.com/js/js_functions.asp

It is JavaScript Hoisting thing, Simply in other words, we are trying print the value of the variable , which is not holding any value
Javascript will render the above code as:-
var myVar1
alert (myVar1)
return false
To clarify more i refered the link javascript hoisting: http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

Related

Can we change the execution context of the browser's JavaScript from Window object to something else?

Assume I have a legacy file called module.js which is like this:
a=1;
This by default attaches to the window object polluting the global (actually window) scope when you execute it in the browser.
Is it possible for me to attach it to a different object instead without changing the contents of the source code?
Since the only real problem is the execution context and nothing else, an ideal solution would be something like this:
change execution context from window to module object;
execute the code;
change execution context from module to window object;
If this is not possible, adding wrappers (like IIFE) to the source code is fine as long as the inner contents are not changed. Changing the inner contents needs a full scan of the code which is expensive.
I can, for example, wrap it into a function like this (✓):
function module()
{
a=1;
}
If it is executed in strict mode, I can avoid global scope pollution. However, I can't get hold of the object.
I don't want to do something like this (✗):
module = function module()
{
return a=1;
}
because we need to add return wherever there is an assignment and that means scanning the entire code.
I am just trying to see ways to improve legacy code meant for the browser with minimal effort.
The answer to the first question, no it is not possible to change the default execution context in the browser. window is a special variable and assigning anything else to it will not change default execution context. See Global Object in MDN. And here is an illustration
(function() {
window = {}
a = 5 // leaking declaration
var b = 10
})()
console.log(a) // a is on global scope
//console.log(b) // exception b is not defined in this scope
var b = 5
window = new Object()
window.c = 5
console.log(window.b) // 5
console.log(c) // 5
The answer to the second part about how to work with legacy code, there are many tools which do AST transformation and depending on your goal you should probably use one or more of them.
jscodeshift allows you to write codemods which are functions that receive code and apply transformations to it. This is probably the most powerful tool in this category.
ESLint allows you to set rules (for example no global vars) and have a --fix option which will apply automatic fixes in some cases like changing from single quote to double quotes (this is mostly for style related rules).
prettier is a code formatter only concerned with code appearance: indentation, spaces etc.
AST Explorer an online tool that lets you see the internals of all the above tools very useful to understand how it works and try code on small examples.

Newly defined variable reporting "undefined" in functions while the rest are not?

I've had a problem where some of my declared and defined variables have been reported as undeclared when it's time to use them inside a function.
So I've been playing about with it, and it seem like no - whenever I add anymore new variables, they are defined straight after they are defined in code, then inside function blocks they indeed reported undefined.
I have been using resources and not been releasing them, like URL objects and connections to databases, and so wonder if it's because I run out of memory?
So I rebooted my phone - no go. Besides, the older variables defined beneath the newer variable are reporting that they are indeed defined? while the new variable still arn't.
For more clarification, here's what visual studio is reporting:
^Every one of those variable in that block work correctly except for 'newVar' and any other newly defined variables
(disclaimer: I'm not a professional - only a hobbyist, and any code shown does not represent production ready code, thank you!)
Example issue code:
(function() {
"use strict";
var variable1,
variable3 = 10,
variable2 = 100,
function clickHandler() {
console.log(variable1); //prints "undefined" in green text.
console.log(variable2); //prints "100"
console.log(variable3); //prints "'variable3' is undefined" in red text
}
clickHandler();
})();
Developing a Windows Phone 8.1 app using latest public SDK, writing in javascript on Windows 10, inside Visual Studio 2015 community edition.
In reference to my comment, I'll take your response as a "no", the suggested example output is not what you'd get if you actually ran that code - I'll explain why I ask...
What you are referring to is called lexical scoping and it's a core concept - you can reliably access outer variables in a function closure and indeed your example runs without issue - at least on the V8 engine, I'm not in a position to test in a Microsoft flavoured environment right now.
The only notable observation that you could make from it (aside from the typo) would be the use of a function as a statement rather than an expression. See this post on the differences between the two - I've not spent any length of time investigating but it's conceivable that Javascript hoisting order could have quirky behavioural differences across different Javascript engines.
This is probably a red herring though because you'd expect all variables to appear as undefined in such cases - it's easy to verify if this is your issue however by simply swapping out the function declaration:
function clickHandler(){ // ... swap this function statement
var clickHandler = function(){ // ... for this function expression
Now onto what I suspect is actually the problem. I can't see the onPinch function in it's entirety on your screenshot but from what I can see there is no reference to newVar inside of it. The error in your console was not produced by your code but by your attempt to inject a reference to the variable via the debugger, into the execution context after it had been resolved.
When your code is running, the compiler won't just dump everything that was in lexical scope into the local context - it's going to make optimisations, i.e. you can't stick a break-point inside the function and expect to see a parameter that isn't used by the function in your actual code.
If you want to to play around with that variable in the console, make an arbitrary reference to it somewhere - for example, even the following will ensure it's in scope:
function onPinch(ev){
newVar;
//...
}
In your example the var line needs to be terminated with a ;
var variable1,
variable3 = 10,
variable2 = 100;
variable1 will then be the only undefined variable in the clickHandler function.

Why single var is good in javascript?

Can anyone tell me why use one var declaration for multiple variables and declare each variable on a newline consider is a good programming behavior?
// bad
var items = getItems();
var goSportsTeam = true;
var dragonball = 'z';
// good
var items = getItems(),
goSportsTeam = true,
dragonball = 'z';
It is not considered 'good' or 'bad'. It's a matter of preference.
The guy who built the code quality tool JSLint, Douglas Crockford likes it.
One 'advantage' it might have is that it avoids the possibility of variable hoisting. In JavaScript all var declarations move to the top of their scope automatically.
Here is why Crockford thinks the second option is better:
In languages with block scope, it is usually recommended that variables be declared at the site of first use. But because JavaScript does not have block scope, it is wiser to declare all of a function's variables at the top of the function. It is recommended that a single var statement be used per function. This can be declined with the vars option.
It's a preference, I wouldn't say good or bad. Yes JSLint complains about it, I don't really like how it complains about for loop variables being inline as well. The reason that it was put in JSLint was to prevent possible hoisting confusions.
Also in some cases declaring all of your variables at the top will lead to a slightly smaller file. Consider the following:
var a = 10;
a++;
var b = 20;
After Google Closure being run over it
var a=10;a++;var b=20;
As opposed to this if we pull b's declaration to the top.
var a=10,b;a++;b=20;
The main benefit (aside from style preference, I guess) is that it will prevent you from writing code that suffers from unintended variable hoisting consequences.
Take this example:
var foo = function(){alert('foo');}
function bar(){
foo();
var foo = function(){alert('foobar')};
foo();
}
bar();
By reading this code, the intent of bar appears to be as follows:
Call the outer foo function to alert the string 'foo'.
Create a local variable, foo.
Call the local foo function to alert the string 'foobar'.
In reality, what happens is this:
The local variable foo is hoisted to the top of the bar function.
foo now actually refers to the local variable instead of the outer variable of the same name. But since the local hasn't been assigned yet, its value is undefined. Hence, when you try to invoke foo, you'll get a TypeError.
Nothing. Because you threw an error. That's it. Your code broke.
The arguments for Crockfords preference have been well made and are valid. I am just beginning to return to the first format now however, as I believe that for experienced developers who understand variable hoisting and are not likely to fall foul to it, there are 2 advantages that I can think of:
When new variables are added to the list of definitions, diffing is made easier. This means you are likely to experience fewer merge conflicts (simple though they may be to resolve) and less cognitive load when analysing diffs. For similar reasons I have also been converted to dangling commas, which I would never have expected xD
As #ldsenow identified, it can make searching for variable definitions more simple. You will always be able to search for var <name> and get the result you want and nothing else.

Why variable hoisting after return works on some browsers, and some not?

alert(myVar1);
return false;
var myVar1;
Above code throws error in IE, FF and Opera stating that return statement has to come in the function. But it works (shows undefined) in Safari and Chrome.
The above code has been written in global scope. Outside all the functions.
Any reason?
In JavaScript variables are moved to the top of script and then run. So when you run it will do
var myVar1;
alert(myVar1);
return false;
This is because JavaScript doesn't really have a true sense of lexical scoping. This is why it's considered best practice to have all your variables declared at the top of the area they will be used to prevent hoisting causing a problem. JSLint will moan about this.
This is a good article that explains it: http://www.adequatelygood.com/2010/2/JavaScript-Scoping-and-Hoisting
The return is invalid. If you want to do a true hoisting example (taken from the link above) do
var foo = 1;
function bar() {
if (!foo) {
var foo = 10;
}
alert(foo);
}
bar();
This will alert 10
Below is my understanding and I have read it somewhere but can't find all the sources that I read so am open to correction.
This Alerts thanks to the differences in the JavaScript JIT. TraceMonkey(http://ejohn.org/blog/tracemonkey/) I believe will take the JavaScript and do a quick static analysis and then do JIT and then try to run it. If that fails then obviously nothing works.
V8 doesn't do the static analysis and moves to the JIT then runs so something. It's more akin to Python. If you run the script in the Developer console (ctrl+shift+j in Windows) in Chrome it will throw an error but also run to give you the alert.
Sometimes hoisting is explained in a way which may give wrong impression, i.e. the variables and functions are hoisted by JavaScript engine as if they were physically moved on top, which is not actually right, as demonstrated by the code below:
console.log(a);
var a = 'Hello World!';
What we see on console is undefined, not 'Hello World', so we got the behavior of the following code
var a;
console.log(a);
a = 'Hello World!';
not the behavior of
var a = 'Hello World!';
console.log(a);
which you may get the impression from the variables and functions declaration being moved to top statement.
But JavaScript is not actually moving your code anywhere. You need to understand execution context in JavaScript. It has two phases creation phase and execution phase. In creation phase memory space is created for these variables and functions, and people seem to confuse this step with hoisting. JavaScript is actually not moving your code anywhere, what happens is JavaScript has created memory space for all your code i.e. variables and functions, functions can be placed fully in memory but in case of variables the assignments are processed in execution phase of the execution context. So when you do var a = 'Hello World!', JavaScript engine knows the value of a when it starts executing it in execution phase of execution context, so it puts a placeholder undefined, and all variables are initially set to undefined in JavaScript. So it is not good to rely on hoisting and see undefined. So it is always good to declare variables and functions on top of your code.
Section 12.9 (page 75) of ECMA-262 edition 3 states:
An ECMAScript program is considered syntactically incorrect if it contains a return statement that is not within a FunctionBody.
That is, a return outside of a function is a syntax error. If a syntax error occurs, no code is run. Think about your example as if you had written:
alert(myVar1);
return false;
syntax error))))))))))))))))));
In addition, section 16 (page 157) states:
An implementation may treat any instance of the following kinds of runtime errors as a syntax error and therefore
report it early:
Improper uses of return, break, and continue.
Firefox's engine et. al. (i.e. those JavaScript implementations which allow return in the global scope) may be conforming, assuming the following clause (in the same section) allows for implementation definition of return in the global scope:
An implementation shall report all errors as specified, except for the following:
An implementation may provide additional types, values, objects, properties, and functions beyond those described in this specification. This may cause constructs (such as looking up a variable in the global scope) to have implementation-defined behaviour instead of throwing an error (such as ReferenceError).
This code makes little sense:
The var myVar1 will never be ran.
The return false; will not return a thing since you're not in a function
Opera, IE and FF are right to throw an error because this code is really not valid since you're not able to return unless you are in a function.
If it works in Safari and Chrome it must be because the javascript engine they use is ready to handle buggy code. My guess would be that they see the "return" and drop or replace it with some kind of break.
More information about functions: http://www.w3schools.com/js/js_functions.asp
It is JavaScript Hoisting thing, Simply in other words, we are trying print the value of the variable , which is not holding any value
Javascript will render the above code as:-
var myVar1
alert (myVar1)
return false
To clarify more i refered the link javascript hoisting: http://www.ufthelp.com/2014/11/JavaScript-Hoisting.html

Have Firebug break when a global variable x is defined

We have a very large JavaScript application, where after many months of coding there have inevitably sprung a couple scope slip ups where a variable is defined without using the var keyword in the following fashion:
function() {
x = 5; ...
}
instead of:
function() {
var x = 5; ...
}
This is happening somewhere - we're not sure where - and searching for the variable name in question is difficult, since it's a common word that appears 1000s of times in our source.
Is there a way to ask Firebug to break on the line that first creates a given global variable? To clarify, I would like to break at exactly the instant when window.x switches from undefined to a defined value, and to break statement.
I've tried creating a watch expression and hoped I could turn it into a breakpoint, but I can't seem to create watch expressions without some kind of context or scope.
If this isn't possible with Firebug, I'd be interested in anything that can accomplish this in Firefox in general.
Provided a few things
You know the name of the variable
You don't have a variable with that name in the global scope (declared outside functions), but only inside functions.
There are calls to the function that declares the variable.
this little script would do the trick:
<script type="text/javascript">
window.__defineSetter__("x", function(value) { console.trace(); });
x = 1;
</script>
You'll get a trace of the executed code before that assignment.
It may fail to report some situations, so take a look at JSLint. Load all your JS files right there and lint them.
Here's another solution that only works in Firefox because it uses the Firefox-specific watch method.
Put this piece of Javascript at the very top of your html page, just after the <head> tag:
<script>
window.watch('x', function() { debugger });
</script>
Note that watch works on any Javascript object (window is the global Javascript object).
Here's the solution I ended up using by modifying Ionut G. Stan's solution:
window.__defineSetter__("name", function(value) {
if (value=="div") {
debugger;
}
});
I used debugger instead of console.trace(), so I could stop and look at it mid-execution. With console.trace() I got a bazillion trace statements due to this line executing many times.
The leaky scope turned out to be buried in Dojo, where Dojo is setting that variable to the name of a processed element.
View your web page on the SeaMonkey browser (I use version 1.1.16) and look at the error console, you will see a message of this type for each assignment to an undeclared variable :
Warning: assignment to undeclared variable x
Source File: http://....js
Line: ##
In addition to debugging, I would advise to check your code with JSLint, which reports unexpected assignments in the global scope as errors.
There are several command-line bundles of jslint, such as jslint4java which can be used cross-platform in Ant build scripts.

Categories

Resources