JavaScript factory constructors

In JavaScript, a constructor is simply a function. In order to use a function as a constructor, you call it using the new keyword. When you use this keyword, a new instance of the function is created and the constructor function executes in the context of the new instance. In other words, this within the constructor function will refer to the new instance that's being created. The constructor will also implicitly return this (the new instance).

function Birthday(name) {
  this.name = name;
}

new Birthday('Jimmy'); // creates a new Birthday instance

The above code would create a new instance of Birthday, whose name property would be set to Jimmy. Because the constructor is just a function, it can be called normally, without the new keyword. This can be quite dangerous however, because when new is left out, this will refer to the global object instead of the new Birthday instance you're trying to create.

function Birthday(name) {
  this.name = name;
}

Birthday('Jimmy'); // assigns a new global variable

In this example, new is not used, so this within the constructor function is the global object and we're assigning the value Jimmy to the global variable, name. It's very unlikely that this is intended, and as with all global variables, it can cause some major headaches. So how can you prevent the constructor function from being used this way accidentally? A solution is to use the constructor as a factory, where the constructor itself looks at what is happening and decides what to return. Take a look at this:

function Birthday(name) {
  if (this === window) {
    return new Birthday(name);
  }

  this.name = name;
}

new Birthday('Jimmy'); // creates a new Birthday instance
Birthday('Jimmy'); // also creates a new Birthday instance

As I mentioned, a constructor function will implicitly return this. But that behavior can be overridden by explicitly returning another object. In this case, the constructor function checks to see if it was called in the context of the global object. If it was, it calls itself in the correct context using new and returns the new instance returned by that invocation. If it is not called in the global context, it behaves as it does normally, setting the name property and implicitly returning the new instance. This allows you to call the constructor with or without the new keyword with exactly the same effect.

Checking for one key among several in a Ruby hash

I've been hard at work on More Things Need To this weekend and have learned lots of things in the process. One of these things was a handy bit of Ruby that seemed worth sharing for other newcomers.

What I wanted to do was find out if any key from a list of keys existed in a hash. For example, given a hash animals, I'd like to know if it contains at least one key among the keys horse, frog, and cow. Checking for a single key is easy:

animals.key?('horse')

But what about when we want to check for all three of those animals? Well, we could just do one after another:

animals.key?('horse') || animals.key?('frog') || animals.key?('cow')

But that can get cumbersome very quickly. There are a few cleaner ways to do this for multiple keys, but the method I ended up using takes advantage of the fact that the Array class in Ruby includes the Enumerable module, which has a handy method called any?. This method takes a block and will return true if any invocations of the block return a "truthy" value. So, here is the solution:

['horse', 'frog', 'cow'].any? do |key|
  animals.key?(key)
end

So what is happening here? First, we're defining an array that contains all the keys we want to check for. Then we call the any? method on that array and pass it a block. Inside the block, we check if the key in the current invocation exists in animals. If an existing key is ever found, the entire call will return true. This removes some repetition and makes the code easier to read.

Note that you can also find out if the hash contains all of the keys rather than just one by using the all? method instead of any?.

Do websites need to look the same in every browser?

There are numerous awesome new features introduced in HTML5 and CSS 3, but neither specification is finalized and browser support for them is still pretty unreliable. After getting a taste of what these new technologies can do, it can be hard to resist using them and to wait for better browser support. My position for a long time has been that, although it's frustrating as a developer, it's best to create things for the lowest common denominator and not use features that don't have reliable support across browsers. But my thoughts on the subject have been changing recently.

One of the catalysts for this change was a spectacular quote from Douglas Crockford that I came across:

If a web browser is defective, causing errors in the display or performance of the page, should the page developer struggle to hide the browser's defects, or should the defects be revealed in hope of creating market pressure to force the browser maker to make good? By which approach is humanity better served?

The debate as to whether or not a developer should support bad, buggy browsers (henceforth referred to as IE) is not a new one. Most often it is simply not a choice for the developer. Most businesses will require support for IE due to its sheer market share and the monetary consequences of not doing so. Even on a project without requirements dictated by an employer, choosing not to support IE puts you at a disadvantage, because chances are there are other developers out there making similar products that do support IE. And when faced with a choice, which are clients going to choose?

Because of these reasons, I've always erred on the side of caution and supported IE. But reading that insightful quote from Douglas Crockford reinvigorated the debate in my mind. I started to rethink how important supporting IE really is and how to find a better compromise in regard to feature support in browsers. There's an emerging school of thought that we should rid ourselves of the preconception that a website should look exactly the same in every browser. I've seen this new attitude come up in several different places recently.

So, does a website need to look the same in every browser? The short answer: no.

My new attitude is to think of browser support with a progressive enhancement approach. I can dramatically improve the look of a site with new CSS 3 effects such as box-shadow. But IE doesn't support it. Should I forego its use? Or use some JavaScript to recreate the effect? Neither! I should use it. Users with browsers that support it will see the fancy version, and IE users will see something more basic, but still fully functional. Since they have not seen it any other way, they're not disappointed, and nothing looks wrong or broken. They're none the wiser.

I feel that this approach is a good compromise on what Douglas Crockford's quote suggests. Instead of crying, "IE be damned!" and allowing it to break, it inverts the sentiment to use a positive context. Instead of punishing IE users for using an outdated browser, it continues to present the baseline for them, and rewards users of modern browsers with extra sparkle. This encourages the use of modern browsers just like the "let IE break" attitude, but keeps everything perfectly useable and presentable to the least common denominator.

Page 13