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.
Related
I ran into a issue eventually it turned out because I did not use var prefix during declare a local variable within a function, so when it get to next function it actually automatically pick it up the variable, even though that was a syntax mistake as my initial intent is to use another local variable with similar name. So is there a setting on google apps script to throw error on a global variable declaration within function to avoid this kind of tricky issues?
Here is sample code of my problematic issue
function f1(){
for(var idx=0;idx<length; idx++){
tmp1 = idx; // since tmp1 missing var, it endup as global variable
...
}
}
function f2(){
Logger.log(tmp1);// even though I did not delcare tmp1 here, it will not throw either validation nor runtime error.
}
Use the JavaScript strict mode. To do this, add the following at the global scope:
'use strict';
The above string literal could be added on any file in your Google Apps Script project, just be sure to add it outside of any function. In order to make this easier to find, add it on top of your project's first file.
Resources
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode
Related
Enforcing strict mode in google-apps-script files using Chrome on Chromebook
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
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.
I'm struggling with (what I believe to be) a scoping issue. Here's a sample of my code:
$(document).ready(function() {
var counter = 0;
function scrollTweets() {
counter ++;
// rest of code
}
...
)}; // end of document ready
When I look up the variable counter in Chrome's Javascript console it returns "ReferencedError". However, when I remove var from the code above and type counter into the console, it returns the value. Why is this?
I think understanding this simple concept would allow me to tackle issues that seem to pop up during development. Is it just a scoping issue on Chrome's part? Am I needlessly wrapping everything in the $(document).ready "function"?
The var locks the variable counter into whatever the lexical scope is -- which means its available in the current block, method, whatever, and can be attached to closed-in scopes (ie. closures), like you are doing with scrollTweets. So counter is only available in the ready callback and anything that has a closure around it, which is why you can't access it from your console.
When you take the var away, counter is effectively global, which is why you can access it in that case.
When you don't use var to set the scope of the variable, it automatically becomes a global variable, inside the global scope. That's why it is visible in the Chrome console.
As a note, I'm by no means implying you should make the variable global. In fact that's almost always a bad idea! Capturing the variable in the context of the scope where it's used is the right thing to do. If the Chrome console can't handle that you just need a better debugger. Firebug for Javascript does a wonderful job at handling scope - even clojures!
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