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

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';
}

Related

'use strict' not stopping hoisting in function scope

My Problem Lies here I'm learning JavaScript But not new to Programming at all.
I understand hoisting, but with strict mode shouldn't this produce an error and be caught either when 6 is assigned to undeclared a variable or document.getElement... is assigned x this doesn't produce an error so my diagnosis is that hoisting is still going on..which i don't like and want to get rid of with using strict. Using Chrome Version 42.0.2311.152 m as my browser
function strictMode(){
'use strict';
try {
x = 6;
document.getElementById('hoisting').innerHTML = x;
var x;
}
catch(err) {
document.getElementById('error_report').innerHTML =
"There was an error that occured (Were in Strict Mode)" +
" " + err.message;
}
}
Variable declarations (i.e. var x;) are valid for the entire scope they are written in, even if you declare after you assign. This is what is meant by "hoisting": the var x; is hoisted to the beginning of the scope, and the assignment x = 6; is fine because x has been declared somewhere in that scope.
Strict mode does not change any of this. It would throw an error if you omitted the var x; declaration altogether; without strict mode, the variable's scope would implicitly be the global scope.
In ES2015 (a.k.a. ES6), hoisting is avoided by using the let keyword instead of var. (The other difference is that variables declared with let are local to the surrounding block, not the entire function.)
There are some weird things javascript allows that, as someone learning the language, you must learn to combat with good coding practices (simicolons are another good example). In the case of hoisting, it is generally good practice to declare your variables at the top of the scope where they would be hoisted to anyway. As already mentioned, strict mode is not a silver bullet and will not enforce this for you.

How to use Global Variables in jQuery

How can i take global variables in jQuery.
this syntax is right that I'm using.
var $val = 2;
or
val = 2; (without using var keyword).
Thnx.
First and foremost: Avoid using global variables whenever possible. It is (almost) always possible. (With apologies to the Dalai Lama)
But answering the question:
If you use var at global scope (outside of all functions), it creates a global variable.
If you just assign to a variable you haven't declared anywhere, if you're not using strict mode (and I recommend you do use it), it will create a global implicitly. This is The Horror of Implicit Globals and should be avoided.
If you really, really need to create a global variable without using var at global scope, you can do that without the Horror by explicitly using the window object:
window.val = 2;
But I reiterate my opening point: Avoid globals.
Here's one way to do that: Use a scoping function around all of your code:
(function() { // <== The start of the scoping function
// Your code here, `var`s here are global to *your* code but not actually globals
// ...
})(); // <== The end of the scoping function, and the () to call it immediately
You should avoid globals even within your code, but by using a scoping function, you at least protect yourself from the outside world (and vice-versa).

Reaching a variable from nested function in Javascript

Can somebody please explain me why the following code works?
function getLastName()
{
fullName.lastName = "World";
}
function writeName()
{
fullName = {};
fullName.firstName = "Hello";
getLastName();
document.write(fullName.firstName + " " + fullName.lastName);
}
writeName();
For some reason, getLastName() can reach local its enclosing method's local state. How can this work? And also should I utilize this feature of Javascript or it is considered as a bad practice? If it is a bad practice, could you please explain why?
You can see the actual code working here at http://jsbin.com/atituk/2/edit
You don't have any local variables, that would require using the var keyword. All your variables are global and can be accessed anywhere within window, which is not considered good practice at all.
You have not used the var keyword against fullName inside the writeName function, you are therefore taking it from the scope outside writeName. It continues up the chain until it reaches the outer most scope, at which point it creates a global.
Globals are, in general, bad practise as they are hard to keep track of and more likely to be overwritten by accident (e.g. in a race condition).
If you were using strict mode this would create an error instead of a global.
You are using all variables of yours as global variables. So all are recognized everywhere. In order to have a better understanding of variable scopes in Javascript have a look at this great example https://stackoverflow.com/a/500459/655316

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

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.

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