> We could always just replace block open and close.
>
> block open with:
> (function() {
>
> block close with:
> }());
>
> would look like this:
> if (something) (function() {
> alert('it's ugly-time');
> }());
>
> Unfortunately, javascript's function literal isn't as awesome as its
> object literal.
Yeah, that's what I meant by 'creating a new function'. In general,
unless you're serious about data encapsulation, you'll only rarely
need to do such a thing. It's also possible to be overzealous about
creating anonymous function blocks: every function block carries with
it a lot of complex operating context information that can have a
performance impact (dynamically creating 1000 new closures with unique
scopes available to them will cause slower browsers and slower
machines to die cruelly).
Were I teaching someone about Javascript in an academic environment, I
would probably spend a lot longer on scope peculiarities with
Javascript than I would with any other language. In one sense, it's
more intuitive because there's no "masking" of more-global variables*,
but it's a lot more confusing because functions are lexically scoped
rather than dynamically scoped**.
If I remember correctly, there was a proposal in Javascript 4 (ECMA6)
that introduced a simple syntactical way to define a new context
without creating a new function. I'm fairly sure it was just sugar for
the code you wrote above, but it would make such code far more
readable. Unfortunately, JS4 is dead for the time being. Most work on
JS these days is in performance enhancements and feature extensions
(see canvas, offline storage, etc) and there's a legitimate argument
that any syntactic changes to JS will "break the web," an eventuality
which has become intolerable as the web has matured.
I'm going to guess that Jacob knows the following, so this is aimed
more at the casual reader interested in learning about Javascript:
* In C-like languages (C++, Java, etc) we can observe the following
behavior. It's unintuitive to assign 10 to an already-existing
variable and have it "mask" it rather than perform an actual
assignment. Removing the "int" changes the behavior in a subtle but
very important way. Using this property of the language is really
powerful, but can lead to logic errors pretty quickly if you aren't
careful.
In javascript, we can write the equivalent and observe the difference.
Assignments that take place within blocks (even if you attempt to
redefine the variable) affect variables of the same name outside the
block.
// C-like language:
int i = 5;
if(1==1) {
int i = 10;
printf("%d\n", i); // prints "10"
}
printf("%d\n", i); // prints "5"
// Javascript
var i = 5;
if(true) {
var i = 10;
console.log(i); // prints "10"
}
console.log(i); // prints "10"
** Lexical scoping is probably one of the trickiest aspects of
Javascript that took me a long time to really internalize and use
properly. It allows for the creation of closures, which are one way to
do data hiding and, with Javascript's built-in scope binding
functions, allow you to bend a function's scope to operate in many
contexts. A basic example:
var push, pop;
(function() {
var array = [];
push = function(el) { array.push(el); };
pop = function() { return array.pop(); };
}());
push("STRING");
alert(pop()); // alerts "STRING"
alert(array) // alerts "undefined";
|