Local Variables and GC - javascript

I'm trying to wrap my head around private variables in Javascript, temporary variables, and the GC. However, I can't quite figure out what would happen in the following situation:
MyClass = function() {
this.myProp = new createjs.Shape();
var tempVar = this.myProp.graphics;
tempVar.rect(0, 0, 10, 100);
tempVar = null;
var isDisposed = false;
this.dispose = function() {
if (isDisposed) return;
isDisposed = true;
}
}
var anInstance = new myClass();
My intention was to have isDisposed represent a private status variable, and tempVar be a use-and-throw variable.
Would tempVar get marked for GC? Would isDisposed be marked for GC too? How is the GC to know when I'm trying to declare a temporary variable meant for disposal, and when I'm trying to have a private variable within the object?
I tried to test the following in Chrome, and it seems as if tempVar never gets GC-ed as long as an instance of myClass exists. So I'm not sure what to believe now. I am incredulous that every single local variable that I create for temporary usage will exist in scope for the lifetime of the object.

Javascript does not have strongly typed objects. By setting tempVar to null, you're not declaring that you don't want to use it any more or marking it for collection as in Java or C#, you're merely assigning it a (perfectly valid) value. It's a trap to begin thinking that just because you made tempVar an "instance" of an object, that the variable is in fact an object and can be treated as such for its whole lifetime.
Basically, variables are just variables in Javascript. They can contain anything. It's like VB or VBScript in that regard. Scalars do undergo boxing in many cases (as in 'a|c'.split('|') making the string into a String) but for the most part, forget that. Functions are first-class objects meaning you can assign them to variables, return them from functions, pass them as parameters, and so on.
Now, to actually destroy something in Javascript, you either remove all references to it (as in the case of an object) or, in the case of an object's properties, you can remove them like this:
delete obj.propertyname;
// or //
delete obj[varContainingPropertyName];
To expand on that point, the following two code snippets achieve identical results:
function abc() {window.alert('blah');}
var abc = function() {window.alert('blah');}
Both create a local variable called abc that happens to be a function. The first one can be thought of as a shortcut for the second one.
However, according to this excellent article on deleting that you brought to my attention, you cannot delete local variables (including functions, which are really also local variables). There are exceptions (if the variable was created using eval, or it is in Global scope and you're not using IE <= 8, or you ARE using IE <= 8 and the variable was created in Global scope implicitly as in x = 1 which is technically a huge bug), so read the article for full details on delete, please.
Another key thing that may be of use to you is to know that in Javascript only functions have scope (and the window in browser implementations or whatever the global scope is in other implementations). Non-function objects and code blocks enclosed in { } do not have scope (and I say it this way since the prototype of Function is Object, so functions are objects too, but special ones). This means that, for example, considering the following code:
function doSomething(x) {
if (x > 0) {
var y = 1;
}
return y;
}
This will return 1 when executed with x > 0 because the scope of variable y is the function, not the block. So in fact it's wrong and misleading to put the var declaration in the block since it is in effect (though perhaps not true practice) hoisted to the function scope.
You should read up on closures in javascript (I cannot vouch for the quality of that link). Doing so will probably help. Any time a variable's function scope is maintained anywhere, then all the function's private variables are also. The best you can do is set them to undefined (which is more "nothing" than "null" is in Javascript) which will release any object references they have, but will not truly deallocate the variable to make it available for GC.
As for general GCing gotchas, be aware that if a function has a closure over a DOM element, and a DOM element somewhere also references that function, neither will be GCed until the page is unloaded or you break the circular reference. In some--or all?--versions of IE, such a circular reference will cause a memory leak and it will never be GCed until the browser is closed.
To try to answer your questions more directly:
tempVar will not be marked for GC until the function it is part of has all references released, because it is a local variable, and local variables in Javascript cannot be deleted.
isDisposed has the same qualities as tempVar.
There is no distinction in Javascript for "temporary variables meant for disposal". In newer versions of ECMAScript, there are actual getters and setters available, to define public (or private?) properties of a function.
A browser's console may provide you with misleading results, as discussed in the article on deleting with Firefox.
It's true, as incredible as it may be, that in Javascript, so long as a variable exists within a closure, that variable remains instantiated. This is not normally a problem, and I have not experienced browsers truly running out of memory due to tiny variables lying around un-garbage-collected. Set a variable to undefined when done with it, and be at ease--I sincerely doubt you will ever experience a problem. If you are concerned, then declare a local object var tmpObj = {tempVar: 'something'}; and when done with it you can issue a delete tmpObj.tempVar;. But in my opinion this will needlessly clutter your code.
Basically, my suggestion is to understand that in coming from other programming languages, you have preconceived notions about how a programming language ought to work. Some of those notions may have validity in terms of the ideal programming language. However, it is probably best if you relinquish those notions and just embrace, at least for now, how Javascript actually works. Until you are truly experienced enough to confidently violate the advice of those who have gone before you (such as I) then you're at greater risk of introducing harmful anti-patterns into your Javascript code than you are likely to be correcting any serious deficit in the language. Not having to Dispose() stuff could be really good news--it's this nasty pervasive task that Javascript simply doesn't require from you, so you can spend more time writing functionality and less time managing the lifetime of variables. Win!
I hope you take my words as kindly as they are meant. I don't by any means consider myself a Javascript expert--just that I have some experience and a solid competence in understanding how to use it and what the pitfalls are.
Thanks for listening!

Related

How do you store activation records with complex lexical scopes and returning functions as results and such?

I have read in several places such as here about "Access Links" and "The Display Method" for looking up non-local variables. However, none seem to touch on the complicated situation like in JavaScript where you can have functions inside of functions, and return those functions from functions, all the while keeping alive the "internal scope" of those functions.
Here is a complicated nested function.
let m = foo()
m()
m()
function foo() {
let x = 10
function bar() {
let y = 2 ** x
function hello() {
let z = 30
function another() {
// PLACE_2
let q = x + y + z
function nested() {
q += (17 * x) - (3 * z)
// PLACE_1
console.log(q)
console.log(w)
}
return nested
}
// PLACE_3
let w = another()
return w
}
return hello
}
// PLACE_4
let a = bar()
let nested = a() // hello returns another
nested()
nested()
return nested
}
At PLACE_1, we are using variables x/z/q, but not y/a/nested. Basically we create all these lingering objects in the scope tree.
How does an activation record with "Access Links" or "Display Method" work in a situation like this? I am used to having functions call other functions, but not keep the environment of past functions around. How do these work in a complex system like this with scopes lingering?
I am trying to implement a compiler and am currently stuck on how to actually implement the Activation Records. I can do it where the activation records are a simple parent/child relationship based on calling order, but I don't see how to make it work with a situation like this. I want to have a sort of variable lookup mechanism, but I don't know what needs to be stored in a situation like this.
Reading something like this doesn't give any insight into real-world situations like this, how it's modeled under the hood.
Displays can only be used if the semantics of the language don't allow non-local variables to outlive their original scope, since the display is basically an efficient eay to find an activation record on the stack. If you want to implement true closures, you'll need to use a different mechanism which involves heap-allocation of enclosed variables. (Unless you can prove that the enclosed variable never escapes. That's often the case, but it can be hard to prove.)
AUUI, Javascript retains the entire activation record of the function call which created the closed variable. But that's dependent on the semantics of the language, and unnecessarily keeping active links to other variables in the activation record prevents them from being garbage collected in a timely manner. It should only be necessary to keep links to the variables actually being enclosed.
Note that there are two distinct cases (again, this depends on language semantics). In the simple case, the captured variable is immutable (although it might contain a mutable value). In that case, you can capture the value by adding it as a data member in the closure. (The closure object itself needs to be heap-allocated but you don't need to do that until the closure is actually created, which might never happen.)
In the more complicated case, the variable itself is mutable and potentially mutated by the inner function [Note 1]. In that case, the variable itself must be "boxed"; that is, enclosed in a container which is used as a handle for the variable. But the mutation might happen before the variable's scope terminates, in which case the change needs to be visible in that scope. If the variable is boxed, the outer function needs to be aware of that because access to the variable is indirect. So boxing the variable onto the heap is a cost which must be paid before it is known to be necessary (depending on the quality of the escape analysis).
That's where the Lua implementation is interesting, at least. It manages to avoid heap-allocating the box in many cases, but there is an additional cost when it does so. That seems to work out well for Lua use cases but I don't know whether it would be a good solution in your case.
Notes:
There's a very common case where a variable is mutable because its value cannot conveniently be computed in a single initialisation expression, but all mutations occur before the variable is captured. Such a variable can be treated as though it were immutable (or as though it was computed and then made the value of a different variable with the same name). That case is fairly easy to detect. (There are also variables whose last mutation is after capture but before the first invocation of a capturing function. Those can also usually be detected.) These variables can be captured as though they were constant, just putting the value into the closure.
Informal surveys indicate that the vast majority of captured variables are either constant or constant-after-capture, which could considerably reduce the need for heap-allocated boxes.

Do we manually need to clean up unreferenced variables in a closure?

I'm reading this article (http://javascript.info/tutorial/memory-leaks#memory-leak-size) about memory leaks which mentions this as a memory leak:
function f() {
var data = "Large piece of data";
function inner() {
return "Foo";
}
return inner;
}
JavaScript interpreter has no idea which variables may be required by
the inner function, so it keeps everything. In every outer
LexicalEnvironment. I hope, newer interpreters try to optimize it, but
not sure about their success.
The article suggests we need to manually set data = null before we return the inner function.
Does this hold true today? Or is this article outdated? (If it's outdated, can someone point me to a resource about current pitfalls)
Modern engines would not maintain unused variables in the outer scope.
Therefore, it doesn't matter if you set data = null before returning the inner function, because the inner function does not depend on ("close over") data.
If the inner function did depend on data--perhaps it returns it--then setting data = null is certainly not what you want to, because then, well, it would be null instead of having its original value!
Assuming the inner function does depend on data, then yes, as long as inner is being pointed to (referred to by) something, then the value of data will have to be kept around. But, that's what you are saying you want! How can you have something available without having it be available?
Remember that at some point the variable which holds the return value of f() will itself go out of scope. At that point, at least until f() is called again, data will be garbage collected.
The general rule is that you don't need to worry about memory and leaks with JavaScript. That's the whole point of GC. The garbage collector does an excellent job of identifying what is needed and what is not needed, and keeping the former and garbage collecting the latter.
You may want to consider the following example:
function foo() {
var x = 1;
return function() { debugger; return 1; };
}
function bar() {
var x = 1;
return function() { debugger; return x; };
}
foo()();
bar()();
And examine its execution in Chrome devtools variable window. When the debugger stops in the inner function of foo, note that x is not present as a local variable or as a closure. For all practical purposes, it does not exist.
When the debugger stops in the inner function of bar, we see the variable x, because it had to be preserved so as to be accessible in order to be returned.
Does this hold true today? Or is this article outdated?
No, it doesn't, and yes, it is. The article is four years old, which is a lifetime in the web world. I have no way to know if jQuery still is subject to leaks, but I'd be surprised if it were, and if so, there's an easy enough way to avoid them--don't use jQuery. The leaks the article's author mentions related to DOM loops and event handlers are not present in modern browsers, by which I mean IE10 (more likely IE9) and above. I'd suggest finding a more up-to-date reference if you really want to understand about memory leaks. Actually, I'd suggest you mainly stop worrying about memory leaks. They occur only in very specialized situations. It's hard to find much on the topic on the web these days for that precise reason. Here's one article I found: http://point.davidglasser.net/2013/06/27/surprising-javascript-memory-leak.html.
Just in addition to to #torazaburo's excellent answer, it is worth pointing out that the examples in that tutorial are not leaks. A leak what happens when a program deletes a reference to something but does not release the memory it consumes.
The last time I remember that JS developers had to really worry about genuine leaks was when Internet Explorer (6 and 7 I think) used separate memory management for the DOM and for JS. Because of this, it was possible to bind an onclick event to a button, destroy the button, and still have the event handler stranded in memory -- forever (or until the browser crashed or was closed by the user). You couldn't trigger the handler or release it after the fact. It just sat on the stack, taking up room. So if you had a long-lived webapp or a webpage that created and destroyed a lot of DOM elements, you had to be super diligent to always unbind events before destroying them.
I've also run into a few annoying leaks in iOS but these were all bugs and were (eventually) patched by Apple.
That said, a good developer needs to keep resource management in mind when writing code. Consider these two constructors:
function F() {
var data = "One megabyte of data";
this.inner = new function () {
return data;
}
}
var G = function () {};
G.prototype.data = "One megabyte of data";
G.prototype.inner = function () {
return this.data;
};
If you were to create a thousand instances of F, the browser would have to allocate an extra gigabyte of memory for all those copies of the huge string. And every time you deleted an instance, you might get some onscreen jankiness when the GC eventually recovered that ram. On the other hand, if you made a thousand instances of G, the huge string would be created once and reused by every instance. That is a huge performance boost.
But the advantage of F is that the huge string is essentially private. No other code outside of the constructor would be able to access that string directly. Because of that, each instance of F could mutate that string as much as it wanted and you'd never have to worry about causing problems for other instances.
On the other hand, the huge string in G is out there for anyone to change. Other instances could change it, and any code that shares the same scope as G could too.
So in this case, there is a trade-off between resource use and security.

What happens to a JavaScript function when it is closured in as a variable?

I've read many questions on closures and JavaScript on SO, but I can't find information about what happens to a function when it gets closured in. Usually the examples are string literals or simple objects. See the example below. When you closure in a function, the original function is preserved even if you change it later on.
What technically happens to the function preserved in a closure? How is it stored in memory? How is it preserved?
See the following code as an example:
var makeFunc = function () {
var fn = document.getElementById; //Preserving this, I will change it later
function getOriginal() {
return fn; //Closure it in
}
return getOriginal;
};
var myFunc = makeFunc();
var oldGetElementById = myFunc(); //Get my preserved function
document.getElementById = function () { //Change the original function
return "foo"
};
console.log(oldGetElementById.call(document, "myDiv")); //Calls the original!
console.log(document.getElementById("myDiv")); //Returns "foo"
Thanks for the comments and discussion. After your recommendations, I found the following.
What technically happens to the function preserved in a closure?
Functions as objects are treated no differently than any other simple object as closured variables (such as a string or object).
How is it stored in memory? How is it preserved?
To answer this, I had to dig through some texts on programming languages. John C. Mitchell's Concepts in Programming Languages explains that closured variables usually end up in the program heap.
Therefore, the variables defined in nesting subprograms may need lifetimes that are of the entire program, rather than just the time during which the subprogram in which they were defined is active. A variable whose lifetime is that of the whole program is said to have unlimited extent. This usually means they must be heap-dynamic, rather than stack-dynamic.
And more specific to JavaScript runtimes, Dmitry Soshnikov describes
As to implementations, for storing local variables after the context is destroyed, the stack-based implementation is not fit any more (because it contradicts the definition of stack-based structure). Therefore in this case closured data of the parent context are saved in the dynamic memory allocation (in the “heap”, i.e. heap-based implementations), with using a garbage collector (GC) and references counting. Such systems are less effective by speed than stack-based systems. However, implementations may always optimize it: at parsing stage to find out, whether free variables are used in function, and depending on this decide — to place the data in the stack or in the “heap”.
Further, Dmitry shows a varied implementation of the parent scope in function closures:
As we mentioned, for optimization purpose, when a function does not use free variables, implementations may not to save a parent scope chain. However, in ECMA-262-3 specification nothing is said about it; therefore, formally (and by the technical algorithm) — all functions save scope chain in the [[Scope]] property at creation moment.
Some implementations allow access to the closured scope directly. For example in Rhino, the [[Scope]] property of a function corresponds to a non-standard property __parent__.

Does encapsulating Javascript code in objects affect performance?

I am wondering if it is more or less efficient to encapsulate the main body of your JavaScript code in an object? This way the entire scope of your program would be separated from other scopes like window.
For example, if I had the following code in a JavaScript file:
/* My main code body. */
var somevar1=undefined;
var somevar2=undefined;
var somevarN=undefined;
function somefunction(){};
function initialize(){/* Initializes the program. */};
/* End main code body. */
I could instead encapsulate the main code body in an object:
/* Encapsulating object. */
var application={};
application.somevar1=undefined;
application.somevar2=undefined;
application.somevarN=undefined;
application.somefunction=function(){};
application.initialize=function(){/* Initializes the program. */};
My logic is that since JavaScript searches through all variables in a scope until the right one is found, keeping application specific functions and variables in their own scope would increase efficiency, especially if there were a lot of functions and variables.
My only concern is that this is bad practice or that maybe this would increase the lookup time of variables and functions inside the new "application" scope. If this is bad practice or completely useless, please let me know! Thank you!
I’ve no idea what the performance implications are (I suspect they’re negligible either way, but if you’re really concerned, test it), but it’s very common practice in JavaScript to keep chunks of code in their own scope, rather than having everything in the global scope.
The main benefit is reducing the risk of accidentally overwriting variables in the global scope, and making naming easier (i.e. you have window.application.initialize instead of e.g. window.initialize_application).
Instead of your implementation above, you can use self-calling functions to create an area of scope just for one bit of code. This is known as the module pattern.
This has the added advantage of allowing you to create “private” variables that are only accessible within the module, and so aren’t accessible from other code running in the same global object:
/* Encapsulating object. */
var application=( function () {
var someprivatevar = null// This can't be accessed by code running outside of this function
, someprivatefunction = function () { someprivatevar = someprivatevar || new Date(); };
return {
somevar1: undefined
, somevar2: undefined
, somevarN: undefined
, somefunction: function(){}
, getInitialized: function () { return someprivatevar; }
, initialize: function (){/* Initializes the program. */ someprivatefunction(); }
};
})();
application.initialize();
application.getInitialized();// Will always tell you when application was initialized
I realize you asked a yes or no question. However, my answer is don't worry about it, and to back that up, I want to post a quote from Eloquent Javascript, by Marijn Haverbeke.
The dilemma of speed versus elegance is an interesting one. You can
see it as a kind of continuum between human-friendliness and
machine-friendliness. Almost any program can be made faster by making
it bigger and more convoluted. The programmer must decide on an
appropriate balance....
The basic rule, which has been repeated by many programmers and with
which I wholeheartedly agree, is to not worry about efficiency until
you know for sure that the program is too slow. If it is, find out
which parts are taking up the most time, and start exchanging elegance
for efficiency in those parts.
Having easy to read code is key to my issue here, so I'm going to stick with the modular approach even if there is a slightly longer lookup chain for variables and functions. Either method seems to have pros and cons as it is.
On the one hand, you have the global scope which holds several variables from the start. If you put all of your code right in the global scope, your list of variables in that scope will include your own as well as variables like innerWidth and innerHeight. The list to search through when referencing variables will be longer, but I believe this is such a small amount of overhead it is ridiculous to worry about.
On the other hand, you can add just one object to the global scope which holds all of the variables you want to work with. From inside this scope, you can reference these variables easily and avoid searching through global variables like innerWidth and innerHeight. The con is that when accessing your encapsulated variables from the global scope you would have a longer lookup chain such as: globalscope.customscope.myvar instead of globalscope.myvar or just myvar.
When I look at it this way, it seems like a very trivial question. Perhaps the best way to go about it is to just encapsulate things that go together just for the sake of decluttering code and keep focus on readability rather than having a mess of unreadable code that is only slightly more efficient.

Why is Coffeescript of the opinion that shadowing is a bad idea

I've wanted to switch to Coffeescript for a while now and yesterday I thought I'm finally sold but then I stumbled across Armin Ronachers article on shadowing in Coffeescript.
Coffeescript indeed now abandoned shadowing, an example of that problem would be if you use the same iterator for nested loops.
var arr, hab, i;
arr = [[1, 2], [1, 2, 3], [1, 2, 3]];
for(var i = 0; i < arr.length; i++){
var subArr = arr[i];
(function(){
for(var i = 0; i < subArr.length; i++){
console.log(subArr[i]);
}
})();
}
Because cs only declares variables once I wouldn't be able to do this within coffeescript
Shadowing has been intentionally removed and I'd like to understand why the cs-authors would want to get rid of such a feature?
Update: Here is a better example of why Shadowing is important, derived from an issue regarding this problem on github
PS: I'm not looking for an answer that tells me that I can just insert plain Javascript with backticks.
If you read the discussion on this ticket, you can see Jeremy Ashkenas, the creator of CoffeeScript, explaining some of the reasoning between forbidding explicit shadowing:
We all know that dynamic scope is bad, compared to lexical scope, because it makes it difficult to reason about the value of your variables. With dynamic scope, you can't determine the value of a variable by reading the surrounding source code, because the value depends entirely on the environment at the time the function is called. If variable shadowing is allowed and encouraged, you can't determine the value of a variable without tracking backwards in the source to the closest var variable, because the exact same identifier for a local variable can have completely different values in adjacent scopes. In all cases, when you want to shadow a variable, you can accomplish the same thing by simply choosing a more appropriate name. It's much easier to reason about your code if a local variable name has a single value within the entire lexical scope, and shadowing is forbidden.
So it's a very deliberate choice for CoffeeScript to kill two birds with one stone -- simplifying the language by removing the "var" concept, and forbidding shadowed variables as the natural consequence.
If you search "scope" or "shadowing" in the CoffeeScript issues, you can see that this comes up all the time. I will not opine here, but the gist is that the CoffeeScript Creators believe it leads to simpler code that is less error-prone.
Okay, I will opine for a little bit: shadowing doesn't matter. You can come up with contrived examples that show why either approach is better. The fact is that, with shadowing or not, you need to search "up" the scope chain to understand the life of a variable. If you explicitly declare your variables ala JavaScript, you might be able to short-circuit sooner. But it doesn't matter. If you're ever unsure of what variables are in scope in a given function, you're doing it wrong.
Shadowing is possible in CoffeeScript, without including JavaScript. If you ever actually need a variable that you know is locally scoped, you can get it:
x = 15
do (x = 10) ->
console.log x
console.log x
So on the off-chance that this comes up in practice, there's a fairly simple workaround.
Personally, I prefer the explicitly-declare-every-variable approach, and will offer the following as my "argument":
doSomething = ->
...
someCallback = ->
...
whatever = ->
...
x = 10
...
This works great. Then all of a sudden an intern comes along and adds this line:
x = 20
doSomething = ->
...
someCallback = ->
...
whatever = ->
...
x = 10
...
And bam, the code is broken, but the breakage doesn't show up until way later. Whoops! With var, that wouldn't have happened. But with "usually implicit scoping unless you specify otherwise", it would have. So. Anyway.
I work at a company that uses CoffeeScript on the client and server, and I have never heard of this happening in practice. I think the amount of time saved in not having to type the word var everywhere is greater than the amount of time lost to scoping bugs (that never come up).
Edit:
Since writing this answer, I have seen this bug happen two times in actual code. Each time it's happened, it's been extremely annoying and difficult to debug. My feelings have changed to think that CoffeeScript's choice is bad times all around.
Some CoffeeScript-like JS alternatives, such as LiveScript and coco, use two different assignment operators for this: = to declare variables and := to modify variables in outer scopes. This seems like a more-complicated solution than just preserving the var keyword, and something that also won't hold up well once let is widely usable.
The main issue here isn't shadowing, its CoffeeScript conflating variable initialization and variable reassignment and not allowing the programmer to specify their intent exactly
When the coffee-script compiler sees x = 1, it has no idea whether you meant
I want a new variable, but I forgot I'm already using that name in an upper scope
or
I want to reassign a value to a variable I originally created at the top of my file
This is not how you forbid shadowing in a language. This is how you make a language that punishes users who accidentally reuse a variable name with subtle and hard to detect bugs.
CoffeeScript could've been designed to forbid shadowing but keep declaration and assignment separate by keeping var. The compiler would simply complain about this code:
var x = blah()
var test = ->
var x = 0
with "Variable x already exists (line 4)"
but it would also complain about this code:
x = blah()
test = ->
x = 0;
with "Variable x doesn't exist (line 1)"
However, since var was removed, the compiler has no idea whether you meant meant "declare" or "reassign" and can't help.
Using the same syntax for two different things is not "simpler", even though it may look like it is. I recommend Rich Hickey's talk, Simple made easy where he goes in depth why this is so.
Because cs only declares variables once the loop will not work as intended.
What is the intended way for those loops to work? The condition in while i = 0 < arr.length will always be true if the arr is not empty, so it will be an infinite loop. Even if it's only one while loop that won't work as intended (assuming infinite loops are not what you're looking for):
# This is an infinite loop; don't run it.
while i = 0 < arr.length
console.log arr[i]
i++
The correct way of iterating arrays sequentially is using the for ... in construct:
arr = [[1,2], [1,2,3], [1,2,3]]
for hab in arr
# IDK what "hab" means.
for habElement in hab
console.log habElement
I know that this answer sound like going off on a tangent; that the main point is why CS discourages variable shadowing. But if examples are to be used to argument in favour of or against something, the examples ought to be good. This example doesn't help the idea that variable shadowing should be encouraged.
Update (actual answer)
About the variable shadowing issue, one thing that it worth clarifying is that the discussion is about whether variable shadowing should be allowed between different function scopes, not blocks. Within the same function scope, variables will hoist the whole scope, no matter where they are first assigned; this semantic is inherited from JS:
->
console.log a # No ReferenceError is thrown, as "a" exists in this scope.
a = 5
->
if someCondition()
a = something()
console.log a # "a" will refer to the same variable as above, as the if
# statement does not introduce a new scope.
The question that is sometimes asked is why not adding a way to explicitly declare the scope of a variable, like a let keyword (thus shadowing other variables with the same name in enclosing scopes), or make = always introduce a new variable in that scope, and have something like := to assign variables from enclosing scopes without declaring one in the current scope. The motivation for this would be to avoid this kind of errors:
user = ... # The current user of the application; very important!
# ...
# Many lines after that...
# ...
notifyUsers = (users) ->
for user in users # HO NO! The current user gets overridden by this loop that has nothing to do with it!
user.notify something
CoffeeScript's argument for not having a special syntax for shadowing variables is that you simply shouldn't do this kind of thing. Name your variables clearly. Because even if shadowing would be allowed it would be very confusing to have two variables with two different meanings with the same name, one in an inner scope and one in an enclosing scope.
Use adequate variable names according to how much context you have: if you have little context, e.g. a top-level variable, you'll probably need a very specific name to describe it, like currentGameState (especially if it's not a constant and its value will change with time); if you have more context, you can get away with using less descriptive names (because the context is already there), like loop variables: killedEnemies.forEach (e) -> e.die().
If you want to know more about this design decision, you may be interested in reading Jeremy Ashkenas opinions in these HackerNews threads: link, link; or in the many CoffeeScript issues where this topic is discussed: #1121, #2697 and others.

Categories