Showing posts with label JavaScript. Show all posts
Showing posts with label JavaScript. Show all posts

Sunday, October 15, 2006

Namespacing your JavaScript

Namespacing your JavaScript: Uses self-invocation to set up a namespace. I prefer the var SCC = new function() { }; notation.

Tuesday, September 19, 2006

Block Scoping in JavaScript

Contrary to C, JavaScript does not directly support block-level scoping, only at the objects and function levels. (Global scoping is really just scoping within the window object.) Thus, the second outer block alert will be 3, not 2:

function foo0() {
var bar = 2;
alert("outer block: "+bar);
if (true) {
var bar = 3;
alert("inner block: "+bar);
}
alert("outer block: "+bar);
}


Because JavaScript scoping is at the function and object levels, block scoping can be simulated with anonymous functions and anonymous objects.

Function-based Block Scoping



Anonymous functions can simulate block scoping by defining a closure and calling it:

function foo1a() {
var bar = 2;
alert("outer block: "+bar);
if (true) (function() {
var bar = 3;
alert("inner block: "+bar);
})();
alert("outer block: "+bar);
}


The parentheses around the closure are necessary to avoid a syntax error when calling the closure immediately. Formal arguments are also considered to be at the function scope, and they can be used to bind the block scoped variables:

function foo1b() {
var bar = 2;
alert("outer block: "+bar);
if (true) (function(bar) {
alert("inner block: "+bar);
})(3);
alert("outer block: "+bar);
}


Another implementation of block scoping with closures uses the new operator that automatically calls its function:

function foo1c() {
var bar = 2;
alert("outer block: "+bar);
if (true) new function() {
var bar = 3;
alert("inner block: "+bar);
};
alert("outer block: "+bar);
}


The syntax of the new operator is a bit tidier.

Object-Based Block Scoping



Just as an anonymous function can implement block scoping, so too can an anonymous object, using the with statement:

function foo2a() {
var bar = 2;
alert("outer block: "+bar);
if (true) with({ bar:3 }) {
alert("inner block: "+bar);
}
alert("outer block: "+bar);
}


Of all of these examples, the with statement has the tidiest syntax -- but only those members in the anonymous object are block scoped. Thus, variables of both function and block scope can be mixed within the same block:

function foo2b() {
var bar = 2;
var baz = 1;
alert("outer block: "+baz);
if (true) with({ bar:3 }) {
var baz = 4;
alert("inner block: "+baz);
}
alert("outer block: "+baz);
}


In this example, the second outer block alert for baz is 4, because baz still has function scope. It remains to be seen whether this ability to mix scoping is a bug (more confusing) or a feature (more flexible) for the with statement version.

Automatic pullquotes with JavaScript and CSS | 456 Berea Street

Automatic pullquotes with JavaScript and CSS | 456 Berea Street

Monday, August 28, 2006

Javascript: innerHTML vs. DOM

There's some debate about whether Javascript code should be using the DOM or innerHTML. My take is that browsers are designed to parse HTML and we should not reinvent the wheel, because it will only be buggier and
slower. Thus, I feel that the presumption ought to be that innerHTML be used before the HTML is parsed, and DOM afterwards.

Wednesday, August 23, 2006

Crockford on Prototypal Inheritance

Douglas Crockford has put up this intriguing page on Prototypal Inheritance in JavaScript:

Five years ago I wrote Classical Inheritance in JavaScript. It showed that JavaScript is a class-free, prototypal language, and that it has sufficient expressive power to simulate a classical system. My programming style has evolved since then, as any good programmer's should. I have learned to fully embrace prototypalism, and have liberated myself from the confines of the classical model.

. . .

Fortunately, it is easy to create an operator that implements true prototypal inheritance. It is a standard feature in my toolkit, and I highly recommend it for yours.


function object(o) {
function F() {}
F.prototype = o;
return new F();
}


The object function untangles JavaScript's constructor pattern, achieving true prototypal inheritance. It takes an old object as a parameter and returns an empty new object that inherits from the old one. If we attempt to obtain a member from the new object, and it lacks that key, then the old object will supply the member. Objects inherit from objects. What could be more object oriented than that?


It makes sense that since JavaScript is a prototype-based OOP language, its prototyping support should be exploited directly, not used to simulate something we are more used to (here, class-based OOP).

Wednesday, August 16, 2006

JavaScript

Lately, I've been keeping current with my programming skill by learning JavaScript. Douglas Crockford aptly called JavaScript, The World's Most Misunderstood Programming Language. Here's how Crockford put it:

JavaScript's C-like syntax, including curly braces and the clunky for statement, makes it appear to be an ordinary procedural language. This is misleading because JavaScript has more in common with functional languages like Lisp or Scheme than with C or Java. It has arrays instead of lists and objects instead of property lists. Functions are first class. It has closures. You get lambdas without having to balance all those parens.


I got to fall in love with Lisp at CMU, and now with JavaScript I have a powerful, Lisp-like language that comes free on my browser. Also interesting is that JavaScript is a prototype-based object-oriented language.

Nevertheless, grokking this language takes experience, and one of the purposes of this blog is to document some of the lessons learned from the school of hard knocks.