I had this idea that, as soon as you made a closure, all the variables were neatly packaged up and were immutable outside of the closure itself. Then I saw some weird behaviour in Javascript, and investigated further.
Turns out that my assumption was just plain wrong. For instance:
test.pl:
----------------------------------------------
sub say_hello {
my $name = shift;
my $text = 'Hello '.$name;
my $sayAlert = sub { print "$text\n" };
$text = "Not in Perl you don't";
$sayAlert->();
}
say_hello('Bob');
----------------------------------------------
> perl test.pl
Not in Perl you don't
Now, reading that again, it makes sense that I would still have access to the variable in the closure from the same scope in which it was declared. So understandably, this version will work as I originally expected:
test.pl:
----------------------------------------------
sub say_hello {
my $name = shift;
my $sayAlert;
{
my $text = 'Hello '.$name;
$sayAlert = sub { print "$text\n" };
}
my $text = "Not in Perl you don't";
$sayAlert->();
}
say_hello('Bob');
----------------------------------------------
> perl test.pl
Hello Bob
However, try the same thing in Javascript, and it doesn't work:
function sayHello(name) {
var sayAlert;
{
var text = 'Hello ' + name;
sayAlert = function() { alert(text); }
}
var text='How confused am I?';
sayAlert();
}
sayHello('Bob');
---> "How confused am I?"
It turns out that, unlike Perl, creating a new (nested) block in JS does NOT create a new scope. Instead a new scope is created when a function is declared. Oh, and it doesn't give you any "variable text redefined" warnings either.