JavaScript and Vars

A couple of points I wanted to chime in and get other’s opinion on:

First, if but ‘stylistically’ a variable has a strict declaration and you also define the type.

JavaScript, however, has much looser timing then other langs (probably because it is run-time and not compiled), so you can kind of just ‘use’ a variable in an instance case without previously declaring it first.

In other languages this would be bad-- but seeing as it ‘works’, is it a problem with JS? Practically? Stylistically?

The second is a little bit of an ‘old bad habit’, or I recall in school always being taught ‘global vars’ are bad ! I mean I can totally understand this from a ‘code portability’ point of view, as well as from the perspective of code security and encapsulation…

I think they are ‘still’ seen as ‘bad’, but not quite updated my knowledge as to ‘why’. I mean I ‘believe’ JS auto handles a lot of other issues not readily discussed here, like garbage collection.

Is it a security, a mem management issue, what ?

You should be declaring all your variables. You should also be choosing to use strict mode: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Strict_mode

The reason for minimising the number of global variables you use is so that your code will ‘play nice’ with other scripts that might get loaded on the same page, because they’ll share the global namespace and if someone else used the same names, there’ll be trouble.

edit to add: declaring variables in javascript won’t give them an immutable type. There’s basically no type-system at all in js - a variable can be a string one minute, an array the next and then get re-used as an integer. It can make for some very smelly code. This is the problem that typescript is meant to solve.

It is what @r1chard5mith says, but also that programs that depend on global variables are often extremely hard to reason about - if you have variables that are in your program, and the values of those variables can be modified, then you’re likely going to need to know what their values are at any given time to successfully write/debug your program. That’s not feasible beyond absolutely trivial programs, so you tend to get wierd, hard to debug errors.

As an example, one thing that comes up over and over on FCC is people using global variables in the algorithm challenges. So the programs may be totally correct, and will work when people test them in isolation. But the issue arises that all the tests past the first fail. First test passes, but a global value is modified. Then the next test, instead of starting with a clean slate, starts with this globally-set value, modifies it. Then the next test starts with the newly-modified value and so on.

There are times when they are useful, but often the best way to use them is to keep them in a specific place, behind an interface. As an example, if you encounter Redux, that works by just keeping the entire state in a single object that you can only access/update in a very specific way. But [the interface to] that object needs to be accessible to your entire program.


Also, the two newer variable keywords, const and let are there to replace var (which cannot be deprecated or have how it works be changed), to prevent some of the issues with it that you kinda touch on in your first question. const is the more useful of the two; it has to be assigned a value in initialisation, and cannot be redeclared or rebound within a scope.

What you wrote there doesn’t make much sense and it sounds like you’re unclear on how JavaScript works. Every language has a run-time aspect, that’s not really unique to JS. Using programmer jargon, JS has dynamic and weak typing—loosely, dynamic means that the type isn’t set and could change during runtime, and weak means that the type is allowed to change. Languages like C++ and Java, on the other hand, have static and strong typing—static means that types are determined at compile time, and strong means that the type isn’t allowed to change.

Pure compiled languages (C/C++) and interpreted languages (Python, JS, Ruby) each have their pros and cons, neither is objectively better than the other. Compiled languages typically do result in faster-performing applications (interpreted languages will always be slower no matter what), but the advantage of interpreted languages is their flexibility and “automatic” memory garbage collection.

Variable scope is a completely different subject, and yes global variables are still considered bad practice, no matter which language you’re using, whether it was C in the old days or ES6 today. You should always enclose your variables inside a block to prevent potential conflicts.

A few thoughts on the OP…

JavaScript, however, has much looser timing then other langs (probably because it is run-time and not compiled), so you can kind of just ‘use’ a variable in an instance case without previously declaring it first.

I think that’s an overgeneralization. It’s simply that JS will declare the variable for you if you don’t. Some languages won’t do that. That is simply a feature. Is it a strength or a weakness? That is subjective. As mentioned, you can enforce stricter rules with “use strict” is you want. You can go even further with things like typescript.

The second is a little bit of an ‘old bad habit’, or I recall in school always being taught ‘global vars’ are bad ! I mean I can totally understand this from a ‘code portability’ point of view, as well as from the perspective of code security and encapsulation…

It is a bad habit in any language. It is dangerous and indicative of bad program design. But this is a bad habit that can be used or avoided in any language I’ve ever used. Variables should have the narrowest scope they need. If we don’t know how narrow of a scope they need, then we don’t understand our program. Global variables in large programs generally mean bad design.

I think they are ‘still’ seen as ‘bad’, but not quite updated my knowledge as to ‘why’. I mean I ‘believe’ JS auto handles a lot of other issues not readily discussed here, like garbage collection.

Yes, JS handles that for you behind the scenes. Is that a strength or a weakness? Most programming choices involve tradeoffs. Having to handle memory management on your own will allow you to use memory more efficiently and more quickly. But at what cost? Difficulty in programming. Is that a good or a bad thing? It depends on your needs. Do you need a program that micromanages large amounts of memory for the sake of having the leanest, fastest program possible? Then JS isn’t the right choice, perhaps C or even assembly would be a better choice. JS does not claim to be the best language for every situation – no language is. JS is very good at what it does. Don’t pick a hammer if you need a screwdriver. It’s not that a screwdriver is better – it’s good for some tasks and not for others. JS has been optimized for frontend web dev and has prove good choice for some backend needs. But if you need to do millions of complex calculations with complex memory needs, then it isn’t the best choice.

I think that’s an overgeneralization. It’s simply that JS will declare the variable for you if you don’t. Some languages won’t do that. That is simply a feature. Is it a strength or a weakness? That is subjective. As mentioned, you can enforce stricter rules with “use strict” is you want. You can go even further with things like typescript.

Haverbeke’s ‘Eloquent Javascript’ was quite enlightening for me on this point, as coming from other languages, including Java originally, I didn’t realize how ‘loose’ one could be with the type-casting. And, sorry, the word I was looking for was ‘type-casting’ not ‘timing’.

I guess I was thinking about the ‘Automatic Type Conversion’ he speaks about in the first Chapter.

Is it a ‘feature’ ? Honestly I’m not so sure-- Though this not quite a difference of ‘type’ (though could be if your type was very, very tightly defined), I did spend some wayward time at Harvard Extension’s pre-med school in one of my classes heard this great story: http://articles.latimes.com/1999/oct/01/news/mn-17288

Granted this was a difference even of ‘measure’ if you will, but if it is a ‘feature’ it has to be used very carefully.

It is a bad habit in any language. It is dangerous and indicative of bad program design. But this is a bad habit that can be used or avoided in any language I’ve ever used. Variables should have the narrowest scope they need. If we don’t know how narrow of a scope they need, then we don’t understand our program. Global variables in large programs generally mean bad design.

I should be a little more clear here. If ‘everything’ is defined as a ‘global var’, obviously that is quite bad and makes no sense. I think I have already stated by understanding that is not great practice. But even in ES6 where now finally you have ‘const’ is there some particular reason to ‘have’ to encapsulate that const in a function (i.e. not global, it must be ‘passed’).

Granted, when I formally studied some of this in school a lot of the thought was towards training new programmers to work on huge projects by large teams, some of the Agile methodologies also coming into effect, obviously you don’t want someone to even ‘accidentally’ change a crucial var by accidentally naming it ‘just the same’ as it was called in the ‘global’–

I mean cross function variable memory access always a real concern/issue too, but if I am XYZ in my cubicle, assigned to function 1342, the biggest danger is I chose a local variable name that has the same name, unbeknownst to me, as some previous ‘global’-- And of course that is ‘bad’-- It cascades all over the application.

But, if one is a ‘one man team’ and selects global’s judiciously, I just wondered is that still ‘bad’-- Not in the ‘not being a team player’ kind of sense, but is there the risk of memory leaks even in a tightly written language like JS or something like that.

Yes, JS handles that for you behind the scenes. Is that a strength or a weakness? Most programming choices involve tradeoffs. Having to handle memory management on your own will allow you to use memory more efficiently and more quickly. But at what cost? Difficulty in programming. Is that a good or a bad thing?

I have to be honest with you Kevin, I’ve mostly agreed with all the points you have rejoindered, if but to offer my own perspective. I was looking for a discussion and you have provided one and I also am still learning.

Personally I just think these are all really kind of ‘important’ points that perhaps even the beta course is still a bit ‘light’ on-- Even ‘Spectre and Meltdown’ have meant major browser handlers have had to adjust the precision timing of Javascript.

Sometimes the ‘basics’ are ‘no fun’, but I’ve really liked this community project, and I only hope to make it better, in some humble way.

My point is that it is a choice, whether to enforce strict declarations or not or to require strict typing or not. Arguments can be made for either. Different languages make different choices.

With regards to the Mars Climate Orbiter, my understanding was that that was an error in the assumption of units, not type. Presumably (I don’t know the code specifics) it was always a variable of some kind of float. The issue was whether it represented a metric or imperial value. I assume that whatever language they were using did not have a metric and imperial type or a newton-seconds or pound-seconds type. They just had some kind of float and a variable name that didn’t make clear that it was metric. You might call that an issue of variable naming but more likely it is an issue of documentation or leadership. Or you can blame it on the US’s intransigent instance on not joining the rest of the world in adopting the metric system even though it is widely used even by American engineers. I don’t think any programming language could have prevented that.

But, if one is a ‘one man team’ and selects global’s judiciously, I just wondered is that still ‘bad’–

I still think it is a bad idea. Unless the program is small, it is easy to loose track of globals. And in terms of maintainability, anyone that has had to come back and examine their own code after 6 months knows, it is easy to forget what you assumed would be obvious when you wrote it.

I still say that global variables should be used sparingly. Sure, constants that will be used everywhere might make sense. If you are writing a math program and have a constant like PHI, there is little chance that you will reuse that name somewhere else for some other value. Constants are perhaps slightly less dangerous, but variables wreak havoc.

I always work on the assumption that someone is going to have to look at my code and understand that, whether or not that is a fellow coder in a week, or me in a year.

I do not hold that every variable must be local and passed. I occasionally use variables that are available to “this” scope and it’s sub-scopes, essentially a “local” global variable, even if just global to a certain module. I do this if passing it around is going to cause more confusion than is saves.

On some of the small apps I did for FCC, I used a few global variables. Often I’ll put them in a global object called GLOBAL so there is no confusion.

I think global variables are a bad habit, one that should be resisted. It’s not uncommon for beginners to use them and that is fine, but eventually the the size of their project will increase to where that gets increasingly dangerous. Sometimes they hold onto globals because they haven’t learned how to plan their app. They aren’t thinking out what info is needed where.

The “one man team” is less and less common. Apps are now so big that they require a team. We should be using best practices whenever possible, even if we feel they aren’t needed. Firstly, they are often needed even when we don’t realize, and secondly, if we use those best practices they eventually become instinctual - they become the way you think.

I too like to ask the question “why”. Sometimes the rules change. When I started programming a function always had to have one return. Now functions often have a “fail fast” return at the top and a few returns at the bottom. Redux reducers have a return on each case and that is considered good practice. But I understand the logic of the old rule - that it can be confusing to understand a function if it has multiple entries and exits - so I also understand that now we “break” the rule as long as it is clear.

Just about every rule (or principle if you like) has some boundary case where it seems like it would be better to break it. But that doesn’t mean that the rule is not a good idea. Learning to code without globals will save many, many more headaches than it causes.

So, I’m not saying globals are always bad. I’m saying that IMHO, in general they are a bad idea. If we’re starting to use one, we should ask ourselves, Who really needs this variable? Is there a better way to do this? Maybe there are a few cases where that value is truly needed everywhere and passing it around would make too much of a mess. So if one must do something “dangerous”, they at least should know that it is a little sketchy and should do it sparingly and should accordingly document it well. Pounding that rule into people’s heads makes sure that they don’t do it willy-nilly.

hm, code that uses the ‘use strict’ declaration or within ES6 modules will throw an exception if you try to do that, i.e. assign to the global object like foo = 'bar'. That goes double for let and const; they were introduced to fix the issue with var that you touch on. You can declare let like let foo; (no specific value assigned), but you’re effectively declaring it as undefined as with var; you can’t even do that with const.

No general reason (obviously depending on context), but note that ES2015 brought native modules (which already existed out-of-the-box in Node, and have been established for a long time via libraries in other environments). Variables are module scoped, so they don’t leak: generally you need to actually make an effort to create global variables within most non-trivial modern apps. You generally don’t have to do very much to avoid actual globals when building applications, they tend to be hard to create outside of trivial scripts - e.g. current standard in module bundlers (which are necessary for front-end work) require that you specify exactly what you want to be exposed as a global. That doesn’t mean that internally [within modules] you won’t get into problems creating variables that are accessible within the whole module, but that’s more of a state management issue.