Javascript: Variables being leaked into the global scope (Firefox addon) - javascript

I submitted my addon to the AMO direcotry and the editor came back with this:
There are still a number of variables being leaked to the global scope,
probably because you're using them undeclared like...
He did not mention all the problem variables, is there anyway to know which are in global scope / getting leaked?
I have a crapload of variables and it would take ages going through each one of them to make sure they were declared properly with a "var".
Please help!
Thanks!

If you're trying to track down variables that may have been implicitly declared as global because of the omission of var, you could run the code in strict mode. This will give you a ReferenceError if you try to use variables that haven't been property declared.
(function() {
"use strict"; // <-- this runs code inside this function in strict mode
// your code...
test = 'tester'; // gives a ReferenceError
})();
You'll need to run it in a supported browser, like Firefox 4 or higher. The "use strict"; declarative will ensure that any code inside the function will be evaluated using the rules of strict mode.

Besides properly using the var keyword, you should make sure all your javascript is wrappend in a function like this:
(function(){
//Your code
}());
This keeps all your variables within the scope of an immediately invoked function.

Use firefox with firebug, add a break point somewhere appropriate and watch the "window" object, all the variables within the global scope are a member of it.

Related

Is there a way to disable Global Variable Declaration within Function

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

What does JavaScript's strict mode exactly do regarding implicit global declarations?

From MDN article about strict mode:
First, strict mode makes it impossible to accidentally create global
variables. In normal JavaScript mistyping a variable in an assignment
creates a new property on the global object and continues to "work"
(although future failure is possible: likely, in modern JavaScript).
Assignments, which would accidentally create global variables, instead
throw an error in strict mode:
'use strict';
// Assuming a global variable mistypedVariable exists
mistypeVariable = 17; // this line throws a ReferenceError due to the
// misspelling of variable
What does this mean? Does the engine detect if a variable with a similar name already exists(?!) or does strict mode merely prohibit declaring global variables outside of global scope?
The above quotation seems to hint the first possibility but this seems... weird?
The comment in the quoted code is misleading: The "Assuming" part is irrelevant. It should really read: "Assuming that no global variable with exactly this name was defined with let or var,..."
But do note what the purpose was of the code snippet and the comment: to show that in strict mode it is much easier to spot spelling mistakes. In sloppy mode the spelling mistake would go unnoticed (no errors) and you would be working with two variables without knowing it (at least for a while)
As requested, I'll make this into an answer :)
I think you understand what happens here already, and are just getting confused through reading that quote about "assuming a global variable..." too literally. (I will admit it is phrased in such a way as to possibly lead to this confusion though.) The real situation is very simple, and has nothing to do with variables having "similar names" (which JS has no concept of):
What is being talked about is what happens if you assign a value to a variable which has not been formally declared (variables are declared with one of the keywords var, let or const). Not declaring your variables is bad practice, and in strict mode will throw an error - this is a good thing and warns you of your mistake. But in non-strict mode, JS will happily accept this and think you wanted to declare a global variable of that name. This is almost never what you actually want, as it pollutes the global namespace, doesn't inform you of your error, and may lead to all sorts of tricky bugs later.
does strict mode merely prohibit declaring global variables outside of global scope?
strict mode definitely doesn't prohibit declaring global variables from anywhere. In non-strict mode, if you write:
someVar = 't';
it will evaluate to:
window.someVar = 't';
( why is this happening? ) despite of writing inside or outside of a function scope. actually, the line was both declaring and evaluation of variable ( look again, it doesn't have var so it shouldn't declare anything! ).
But it would cause such a side-effect that wasn't totally fine and they've introduced strict-mode which when is active, our first line will throw an error. because it's just evaluation without declaring it first.
now if you need to manipulate global scope inside of a function scope, you only should global object as reference:
var someGlobalVar;
var someOtherGlobalVar;
function hello() {
// this will make *someGlobalVar* to be redefined in the inner scope
// someGlobalVar != window.someGlobalVar
var someGlobalVar;
// manipulating inner variable, not global one
someGlobalVar = 's';
// it's fine, you've accessed global object correctly
window.someGlobalVar = 's';
// you're still editing global object, because
// there's no other variable inside of this scope having the same name
someOtherGlobalVar = 's';
}

Curious scoping difference between local/webserver and JS Bin test

It appears JS strict mode disallows declaring of implicit globals, but does not affect access of variables defined inside a conditional (if) or loop (while). In C#, you cannot access a variable declared within a conditional or loop externally. In JavaScript, however, the following works:
"use strict";
(function() {
var mybool = true;
if (mybool) {
var test = "test;
console.log(test); //"test"
}
console.log(test); //"test"
}());
But it breaks in JSBin and jsFiddle, saying that test1 is out of scope.
Why does it work on my webserver, but breaks elsewhere?. What are the rules on scoping within conditionals and loops and such... is JavaScript supposed to be like C# in this way?
I think you're getting strict mode and JSHint errors confused.
In JSBin, JSHint is issuing the 'test1' used out of scope error. This has nothing to do with strict mode. On your webserver, everything works correctly because strict mode has no opinions on this kind of variable scope issue. JSBin is running JSHint for you, and your web server is probably not.
What are the rules on scoping within conditionals and loops and such... is JavaScript supposed to be like C# in this way?
No. JavaScript has no block scope, but it does have function scope. This means that if a variable is declared inside of a block (like an if statement or loop construct), its declaration is "hoisted" to the top of the function. Check out this great article for more on variable declaration hoisting.
For your code in particular, it's interpreted just as if you've written it like this:
(function() {
var mybool = true,
test; /* = undefined */
if (mybool) {
test = "test;
console.log(test); //"test"
}
console.log(test); //"test"
}());
To avoid this kind of confusion over scope in JavaScript, it's a good practice to declare all of your variables at the top of the function they're in (since that's where they're actually scoped to anyway).

Javascript: is the Windows object a default object?

First time poster. I tried to search for answer before posting.
I'm new to javascript, coming from a Delphi/pascal background. I am used to things having to be explicitly spelled out. When I see code that includes setTimeout or setInterval (see here:
http://www.w3schools.com/js/tryit.asp?filename=tryjs_setinterval1), I notice that it just looks like an intrinsic function. But I think it is actually a method of the Windows object.
So it looks like the "window." part is optional. Is this somethign specific to the Window object? Or will any method that is specified without the name of it's containing object be recognized in javascript? And what would happen if there was another variable in the global scope that had a method also named setTimeout? How would the compiler/interpreter know which one to use?
Thanks so much,
Kevin
In Javascript, there is something called the Global scope. On Browsers, the global scope object is window. If you create a variable outside of a function, it goes by default into the global scope, which is window.
When invoking a method or referencing a variable on the window object, it's optional to include window.
its not windows its window (no 's' at end).
As far as i know javascript have 3 scopes local, [clouser], global
Every variable or function is first looked up in local scope, then clouser and finally if not found anywhere in between it will checked in global scope.
As in image you will see global scope is shown as Window object which mean whatever goes in global scope goes in window object.
copy paste below code in chrome devtools console
function outerFunction() {
var a = 10;
debugger;
function innerFunction() {
'use strict';
var b = 10;
debugger;
console.log(a);
}
innerFunction();
}
outerFunction();
on 1st debug
on 2nd debug

Weird behavior in referring to global variable. Is this a bug in javascript? Surely it isn't!

Consider the following piece of code.
<html>
<body>
<script>
var x = 5; //globally declared
function showX()
{
alert("x="+x); //trying to display global value
var x=10; //trying to create and initialize a local x
}
</script>
<input type = "button" value="Show X" onclick="showX()">
</body>
</html>
The alert statement shows 'x=undefined'. And doesn't print the global value of x as expected. An equivalent java code would display 5! So, is it a bug? If not then how does one explain that behavior?
The ECMAScript Specification says in section 12.2:
If the variable statement occurs
inside a FunctionDeclaration, the
variables are defined with
function-local scope in that function,
as described in s10.1.3. Otherwise,
they are defined with global scope
(that is, they are created as members
of the global object, as described in
10.1.3) using property attributes { DontDelete}. Variables are created
when the execution scope is entered. A
Block does not define a new execution
scope. Only Program and
FunctionDeclaration produce a new
scope. Variables are initialised to
undefined when created. A variable
with an Initialiser is assigned the
value of its AssignmentExpression when
the VariableStatement is executed, not
when the variable is created.
So it's not a bug - the local variable is created when the function is entered.
The second var-declaration is interfering with the first. You are actually referring to the as-of-yet-undeclared local x. However, to quote javascript guru Douglas Crockford:
JavaScript's biggest problem is its
dependence on global variables,
particularly implied global variables.
If a variable is not explicitly
declared (usually with the var
statement), then JavaScript assumes
that the variable was global. This can
mask misspelled names and other
problems.
http://www.jslint.com/lint.html
So the recommendation is to avoid using global variables as much as possible.
The scope of x is the block function in which it is declared... although I believe scope in JavaScript can be a bit tricky sometimes. In C# this would be a compile-time error - it would be trying to use the local variable before its declaration.
Whatever the reason, I'd try to avoid doing it simply for the sake of readability.

Categories

Resources