“JavaScript Patterns” now in Brazilian Portuguese

March 20th, 2011

Padrões JavaScript

I've been terrible at promoting this book. But that should change starting today :)

So today I got a copy of "Padrões JavaScript" - the Brazilian Portuguese translation of JavaScript Patterns. Happy, happy, happy!

Given that I already got two copies few weeks ago, kept one and sent one to my mom for her collection, I thought I should give this one away.

If you want to enter for a chance to win a signed copy of the Brazilian Portuguese translation of JavaScript Patterns, you can do one or more of the following:

  • Leave a comment below, or/and
  • Retweet this

That's it, shipping's on me. Boa sorte!

pssst, here are two PDFs: table of contents and about half of chapter 1 for you evaluation pleasure :)

Book is almost out

September 4th, 2010

The JavaScript Patterns book is to be sent to the printer next week and will be available as expected (and mentioned on Amazon) on or before Sept 28. Yey!

Dunno who said: writers don't like to write, they like to have written. Exactly how I feel today.

And let me share a quote from my favorite Kurt Vonnegut along the same lines. The book is Bluebeard.

    She asked me what had been the most pleasing thing about my professional life when I was a full-time painter -- having my first one-man show, getting a lot of money for a picture, the comradeship with fellow painters, being praised by a critic, or what?
    "We used to talk a lot about that in the old days," I said. "There was general agreement that if we were put into individual capsules with our art materials, and fired out into different parts of outer space, we would still have everything we loved about painting, which was the opportunity to lay on paint."
    I asked her in turn what the high point was for writers -- getting great reviews, or a terrific advance, or selling a book to the movies, or seeing somebody reading your book, or what? She said that she, too, could find happiness in a capsule in outer space, provided that she had a finished, proofread manuscript by her in there, along with somebody from her publishing house.
    "I don't understand," I said.
    "The orgastic moment for me is when I hand a manuscript to my publisher and say, 'Here! I'm all through with it. I never want to see it again,' " she said.

So - whew!

Expect a more detailed post about the book (and the wonderful team of JS guru tech reviewers!), after all I have to start promoting it, don't I?

Singleton without a closure

July 17th, 2010

Warning: anti-pattern ahead.

Mwahaha, I feel like a ninja. I mean a ninja by Doug Crockford's definition which means someone who finds a mistake in the language's design, decides it's cool and abuses it.

So there you go. Regular expression objects are created only once if you're using a literal. Such an object can be used to store the single instance of a Singleton() constructor.

Implementation

function Single() {
    "strict me not!";
 
    var re = / /;
    if (re.instance) {
        return re.instance;
    }
    re.instance = this;
    this.name = "Foo";
 
}
 
Single.prototype.getName = function () {
    return this.name;
};

Test

var s1 = new Single(),
    s2 = new Single();
 
console.log(s1 === s2); // true
console.log(s1.getName()); // "Foo"
s1.name = "dude";
console.log(s2.getName()); // "dude"

Pros

  • The prototype chain works fine
  • No closures
  • No public properties or globals to store the single instance

Cons

  • It's a hack
  • ES5 defines that reg exp literals should no longer work like this

Verdict

Don't use. Please :)

Constants

April 10th, 2010

Although there actually are constants in some environments, e.g. in Firefox you can use const instead of var, in general in JavaScript there are no constants.

Workaround

To work around that limitation, people often use ALLCAPPS to denote "hey, don't touch this var, it's meant to be a constant". It's constant-by-convention but the values can be changed by careless programmer on a bad day. If you really want to protect the value, you need to make it private.

PHP-inspired API

In PHP there are the functions define(name, value) to gefine a constant, defined(name) to check if a constant is defined and constant(name) to get the value of a constants when it's name is assembled at runtime and you don't know it a priori. So I thought - well, we can do the same in JavaScript. Only, let's not use global functions, but a constant global var and make the functions method of that global. constant.constant(name) is a little mouthful, so let's make that one constant.get(name)

Implementation

Here's the simple implementation:

"use strict";
 
var constant = (function () {
    var constants = {},
        ownProp = Object.prototype.hasOwnProperty,
        allowed = {
            string: 1,
            number: 1,
            boolean: 1
        };
    return {
        define: function (name, value) {
            if (this.defined(name)) {
                return false;
            }
            if (!ownProp.call(allowed, typeof value)) {
                return false;
            }
            constants[name] = value;
            return true;
        },
        defined: function (name) {
            return ownProp.call(constants, name);
        },
        get: function (name) {
            if (this.defined(name)) {
                return constants[name];
            }
            return null;
        }
    };
}());

This is it. Basically protect an object in a closure and don't provide means to change it, but only to add properties to it.

UPDATE: thanks to the comments (see below), there's extra care to check for own properties of the constants private object. This allows to define constants with weird names such as toString and hasOwnProperty. Also only primitive values are allowed to be constants.

Usage

// check if defined
constant.defined("bazinga"); // false
 
// define
constant.define("bazinga", "Bazinga!"); // true
 
// check again
constant.defined("bazinga"); // true
 
// attempt to redefine
constant.define("bazinga", "Bazinga2"); // false
 
// was it constant or it changed?
// get da, get da, get da value
constant.get("bazinga"); // "Bazinga!"

arguments considered harmful

February 16th, 2010

Inside every JavaScript function an arguments object is available containing all the parameters passed to the function.

function aha(a, b) {
  console.log(arguments[0] === a); // true
  console.log(arguments[1] === b); // true
}
 
aha(1, 2);

However, it's not a good idea to use arguments for the reasons of :

  • performance
  • security

The arguments object is not automatically created every time the function is called, the JavaScript engine will only create it on-demand, if it's used. And that creation is not free in terms of performance. The difference between using arguments vs. not using it could be anywhere between 1.5 times to 4 times slower, depending on the browser (more info and bench)

As for the security, there is the POLA (Principle of Least Authority) which is violated when one function A passes arguments to another B. Then a number of bad things can happen including:

  • B calls A through arguments.callee - something A never intended when calling B in the first place
  • B overwrites some arguments and causes A to misbehave

While in these scenarios B looks a little malicious, it can actually cause trouble unvoluntarilly. Consider this example that illustrates the second case (B changing values behind A's unsuspecting back)

function A(obj, ar) {
 
  console.log(obj); // {p: 1}
  console.log(ar);  // [1, 2, 3]
 
  B(arguments);
 
  // oops!
  console.log(obj); // {p: 2}
  console.log(ar);  // [1, 2]
}
 
function B(args) {
 
  // convenient innocent-looking local vars
  var o=args[0],
      a=args[1];
 
  // do something with the local variables
  o.p = 2;
  a.pop();
 
  // now the original arguments is 
  // messed up because objects/arrays
  // are passed by reference
}
 
A({p: 1}, [1, 2, 3]);

ECMAScript 5

In ECMAScript's "strict mode", using arguments.callee will throw a syntax error.

Recursive anonymous function

Probably the biggest argument for keeping arguments and arguments.callee is so that recursive anonymous functions can be created, because by using the callee property a function can call itself without knowing its own name. Now, this is not such a common scenario, but even if so, you can wrap a named function inside of an anonymous function and voila! - call that named function recursively without leaking a variable to the global scope.

Function properties

September 15th, 2009

Since functions are objects, and objects are mutable in JavaScript, you can add properties to your functions.

Why? For caching results of computations for example. Here's a memoization done this way.

function myFunc(param){
    if (!myFunc.cache) {
        myFunc.cache = {};
    }
    if (!myFunc.cache[param]) {
        var result = {}; // ...
        myFunc.cache[param] = result;
    }
    return myFunc.cache[param];
}

Here myFunc() gets a cache property which is an object. The function does the complicated computations based on a parameter and ends up with a result object. Using the parameter as a key in the cache object, it stores the result.

Consecutive calls with the same parameter will get the result from the cache, no need to compute the same result again.

Lazy definition function

September 15th, 2009

This has a nice name a lazy function definition. A lazy function is one that pretends to work but it doesn't really.

It does some work initially and then caches the result. Then on consecutive calls it only returns the pre-computed result, it doesnt really do anything.

In order to do so, the function redefines itself with a new implementation, one that simply points to the computed result.

function lazy() {
    var result = 2 + 2;
    lazy = function() {
        return result;
    };
    return lazy();
}
 
lazy(); // 4
lazy(); // 4

Self-overwriting functions

September 15th, 2009

Next pattern a function that overwrites itself, a self-redefining function. Pretty similar to functions that return functions, but this time the function is re-implemented from the inside, not returned.

function next() {
    var count = 1;
    next = function() {
        return ++count;
    };
    return count;
}
 
next(); // 1
next(); // 2

Returning functions

September 15th, 2009

Functions are objects, so they can be passed around like callbacks for example and also returned by other functions.

You call a function that does some complicated setup and as a results returns a new function. You assign the result to a new function and use it afterwards.

function setup() {
    alert(1);
    return function() {
        alert(2);
    };
}
var my = setup(); // alerts 1
my(); // alerts 2

Your setup function can store some private data in a closure and use that data somehow.

Here setup() creates a counter function, which gives a next ID for example. But the count variable is not exposed.

function setup() {
    var count = 0;
    return function() {
        return ++count;
    };
}
var next = setup();
next(); // 1
next(); // 2

Callbacks

September 15th, 2009

Since functions are objects they can be passed as arguments to other functions.

function test(a, b, fn) {
    fn(a, b);
}

In this simple example we have a function test() that takes a function fn as a third parameter and calls that function passing the first two parameters.

When you cal the test() function, you can pass a pointer to an existing function myFunc() or you can also pass an anonymous function.

test(1, 2, myFunc);
 
test(1, 2, function(one, two){
    console.log(arguments);
});

Examples

For examples of this pattern in the wild well, every time you attach an event listener, you pass a callback function.

document.addEventListener(
    'click', 
    animateAndWowUser, 
    false
);

Same with timeouts and intervals. setTimeout() and setInterval() expect a function and call it back after the specified number of milliseconds.

var thePlotThickens = function(){
  console.log('500ms later...');
};
setTimeout(thePlotThickens, 500);

And here's a common anti-pattern passing a string where a function is expected. The JavaScript engine has no choice but to evaluate the string (like with eval()) and execute it, which is unnecessary work.

// anti-pattern
setTimeout("thePlotThickens()", 500);