JavaScript code snippets and links

Hans's picture
Sun, 2009-09-06 19:15 by Hans · Forum/category:

Introduction

Table of contents

for this article

This article holds a collection of code pieces for re-use. It is expected to grow.

The content is somewhat advanced and not meant for beginners.

Static variables

The following examples show pieces of code that should be used inside functions. They make no sense in the global scope.

JavaScript has no static keyword, although it is one of the reserved words, presumably for future expansion.

But we don't need it for now. Instead of:

static counter; // wrong!

which is wrong, we can, inside a function fn, simply use:

fn.counter

But first we have to initialize it only once, for example, with:

fn.counter = fn.counter || 0;

Or, if this is too javascripty to you, you can write this only slightly longer statement, which has the same meaning:

if (!fn.counter) fn.counter = 0;

So here is a complete example for a web browser, in a function named count, where we can use the alert(…) function:

function count() {
  count.counter = count.counter || 0;
  alert(++count.counter);
}

count();
count();
count();

It will count to 3. Look ma, no globals!

If you want to try it as a simple text file outside a web browser, but inside Microsoft Windows, then copy the following program into a text file, name it count.js, and double-click on it.

function count() {
  count.counter = count.counter || 0;
  WScript.Echo(++count.counter);
}

count();
count();
count();

So how does it work? count is a function, but functions are also objects. Since objects can have properties, this one can have the property counter.

This is also the meaning of the magic "lambda" word in the science of programming languages. In JavaScript functions, which are the same as methods, are first-class objects that can even be applied to other objects by means of the apply or call method. Tell that a Java programmer and he will drop dead. C# programmers at least have a clue. They know them as "delegates".

A block with local variables

As you should already know, JavaScript knows only two variable scopes, function and global. If a newcomer to JavaScript believes that the variable elementStyle in the following (syntactically and semantically correct) piece of code is local to the apparent block, he is in for a bad surprise.

{
  var elementStyle =
      document.getElementById("xy").style;
  elementStyle.color = "red";
  elementStyle.visibility = "visible";
}

In fact, if the block is inside a function, the scope of the variable elementStyle is the function, otherwise it is global, which is even worse.

For this reason the use of such blocks is not recommendable, because it is misleading for programmers, who do not yet know JavaScript inside out, and also totally superfluous. The only places where such blocks are needed is in connection with control flow commands like if, while, for, switch, etc.

Global variables are rather evil, so what can we do? It is simple. In many cases like this, where we want to emulate something we know from other languages in JavaScript, we can actually use a function to do it. This example effectively creates a block with local scope:

(function () {
  var elementStyle =
      document.getElementById("xy").style;
  elementStyle.color = "red";
  elementStyle.visibility = "visible";
}());  

Technically this is a nameless function, which is defined and immediately executed. The effect is the same as that of a block in other languages.

The parentheses behind and around the nameless function definition are needed, because we need to turn it into an expression first, before we can call it. In other words, a function definition cannot be called, particularly not a nameless one, but a function can, by appending parentheses to it and then turning it into an expression with another pair of outer parentheses.

By the way, if you embed a nameless function (inner) in another function (outer), it has access to all variables in the outer function (except for the pseudo-variable this, which is apparently due to an oversight in the design of JavaScript and is planned to be fixed in a future version). The standard workaround (courtesy Douglas Crockford) is the following line in the outer function:

var that = this;

Then refer to that in the inner function.

Fixing the for…in statement

[This and the following are some pieces of code from one of the true masters of JavaScript, Douglas Crockford. Be sure to read his web site, particularly his articles on JavaScript, and watch his lectures.]

The problem is that the for…in statement delivers not only the keys in the object, but also all inherited keys, for example those that had been added to the prototype. Here is the recommended workaround:

for (name in obj) {
    if (obj.hasOwnProperty(name)) {
        …
    }
}

From for in Intrigue by Douglas Crockford

Prototypal inheritance

The following code creates a new object that inherits directly from an old object. Note that JavaScript's new operator does not do this—it inherits from the old object's prototype instead, in a questionable attempt to emulate Java behavior.

Note that JavaScript does not have classes, but it does not need them either.

if (typeof Object.create !== 'function') {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}
newObject = Object.create(oldObject);

From Prototypal Inheritance in JavaScript by Douglas Crockford

Links

Average: 4 (1 vote)