JavaScript: Hitting Bottom #3 – The Crucible of Truthiness

Some programming languages judge truth by the nature of non-zero values (C); some by non-false, non-nil values (Ruby). JavaScript follows it’s gut. If it seems true it’s usually true, if it seems false it’s usually false… usually.

There are two kinds of truth in JavaScript, things that take the `if` branch in `if-else` expressions; and things that == false.

Let’s start with things that == false:

    test("false idols", function() {
      equals(0 == false, true);
      equals('' == false, true);
      equals(' ' == false, true);
      equals('0' == false, true);
      equals([] == false, true);
 
      equals(null == false, false, "!");
      equals(undefined == false, false, "!");
    });

The first thing to note is that empty strings and strings that can be converted to the integer zero are == to false. The second thing to note is that `null` and `undefined` are not == to false. A lot of things in JavaScript == false, actually infinitely many. A lot of different arrays for example:

    test("false Arrays", function() {
      equals([0] == false, true);
      equals([''] == false, true);
      equals([' '] == false, true);
      equals(['0'] == false, true);
      equals([[]] == false, true);
      equals([false] != false, true, "!!! The `toString()` is 'false'");
      equals([null] == false, true);
      equals([undefined] == false, true);
 
      // It goes on like that, the toString ends up as '0'
      equals([[[[[[[[[0]]]]]]]]] == false, true);
 
      // This adds weight to the toString hypothesis
      equals([{toString: function() {return '';}}] == false, true);
      equals([{toString: function() {return '0';}}] == false, true);
    });

Some Objects with particular `toString` methods also == false:

    test("Objects with toString methods defined that are equivalent to false", function() {
      equals({toString: function(){return false}} == false, true, "!!");
      equals({toString: function(){return null;}} == false, true, "!!");
      equals({toString: function(){return '';}} == false, true, "!!");
      equals({toString: function(){return '0'}} == false, true, "!!");
      equals({toString: function(){return 'false'}} != false, true, "!!");
      equals({toString: function(){return undefined}} != false, true, "!!");
    });

Also, as mentioned previously, any strings that convert to the number zero such as:

    test("false Strings", function() {
      equals('                        ' == false, true);
      equals('            0.          ' == false, true);
      equals('0.0000000000000000000000' == false, true);
    });

Sounds like it would be hard to keep track of everything that evaluates to false… but don’t worry it has no effect on if-else statements. For if-else statements only things that are cast to the primitive `false` by Boolean matter. Wouldn’t Boolean cast everything that == false to be `false`? Not on your life!

    test("Boolean Goolean", function() {
      equals(Boolean(false) == false, true);
      equals(Boolean(0) == false, true);
      equals(Boolean('') == false, true);
      equals(Boolean(null) == false, true, "!!");
      equals(Boolean(undefined) == false, true, "!!");
      equals(Boolean(NaN) == false, true, "!!");
      equals(Boolean(' ') != false, true, "!!");
      equals(Boolean('0') != false, true, "!!");
      equals(Boolean([]) != false, true, "!!");
      equals(Boolean(new Boolean(false)) == true, true, "!!!");
    });

The exclamations are included for the ones that == false is different for. The only six things that evaluate to false in an if expression are: false, 0, null, undefined, NaN, and ”. Few enough to count on one hand! Aside from Boolean casting things that == false to `true` and casting things that != false to `false`, the one big thing to watch out for is that all Boolean objects are cast to `true` especially `new Boolean(false)` so don’t use it in your if statements!

Here’s a long boring series of tests to illustrate that the if-else branching does indeed match how Boolean casts things and not whether or not they == false. Exclamations where it’ll getcha. I’ll leave it as an exercise for the reader to skim to the bottom, say “hmmm…..” and then start browsing Reddit (or Hacker News).

    test("if statements", function() {
      var x;
      var ifX;
 
      x = undefined;
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, false);
      if(x != false) { ifX = true; } else { ifX = false; }
      equals(ifX, true, "!!");
 
      x = null;
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, false);
      if(x != false) { ifX = true; } else { ifX = false; }
      equals(ifX, true, "!!");
 
      x = false;
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, false);
 
      x = true;
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, true)
 
      x = 0;
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, false);
 
      x = NaN;
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, false);
      if(x != false) { ifX = true; } else { ifX = false; }
      equals(ifX, true, "!!");
 
      x = '';
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, false);
 
      x = ' ';
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, true);
      if(x != false) { ifX = true; } else { ifX = false; }
      equals(ifX, false, "!!");
 
      x = '0';
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, true, "!");
      if(x != false) { ifX = true; } else { ifX = false; }
      equals(ifX, false, "!!");
 
      x = [];
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, true, "!");
      if(x != false) { ifX = true; } else { ifX = false; }
      equals(ifX, false, "!!");
 
      x = {};
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, true);
 
      x = {toString: function(){return '';}};
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, true);
 
      x = new Boolean(false);
      if(x) { ifX = true; } else { ifX = false; }
      equals(ifX, true, "!!!")
      if(x != false) { ifX = true; } else { ifX = false; }
      equals(ifX, false, "!")
    });

JavaScript: Hitting Bottom #2 – FUNdefined

What better way to understand a language than to understand the basic types? And what can be more basic than `undefined`?

    /**
     * Undefined is generally well behaved.
     */
    test("FUNdefined", function() {
      equals(undefined > 0, false);
      equals(undefined < 0, false);
      equals(undefined >= 0, false);
      equals(undefined <= 0, false);
      equals(undefined == 0, false);
      equals(undefined === 0, false);
 
      equals(undefined == null, true);
      equals(undefined == false, false);
      equals(undefined == true, false);
 
      equals(undefined === null, false);
      equals(undefined === false, false);
      equals(undefined === true, false);
 
      equals(undefined == undefined, true);
      equals(undefined >= undefined, false, "!");
      equals(undefined <= undefined, false, "!");
    });

Pretty much no surprises there. The only thing to watch out for is that `(undefined >= undefined) == false` which makes some sense mathematically, but it might make more sense for it to equal `undefined`.

But where’s the FUN? I wouldn’t have a reputation as a professional ranter about JavaScript if I didn’t rant about JavaScript…

    /**
     * null is pretty weird. It's almost like zero but not equal to false.
     */
    test("null", function() {
      equals(null > 0, false);
      equals(null < 0, false);
      equals(null == 0, false);
      equals(null >= 0, true, "!!!");
      equals(null <= 0, true, "!!!");
      equals(null === 0, false);
 
      equals(null == false, false, "!!");
      equals(null >= false, true, "!!!");
      equals(null <= false, true, "!!!");
 
      equals(null > true, false);
      equals(null < true, true, "!!!");
      equals(null == true, false);
      equals(null >= true, false);
      equals(null <= true, true, "!!!");
 
      equals(null == undefined, true);
      equals(null >= undefined, false, "!");
      equals(null <= undefined, false, "!");
 
      equals(null == null, true);
      equals(null >= null, true);
      equals(null <= null, true);
    });

Legend

  • “!”: “note this!”
  • “!!”: ‘hmm… strange.”
  • “!!!”: “WTF!?!?!”

This set of tests for the behavior of null has a ratio of 22/20 !s/line. That means that there is significant unexpected behavior around `null`. The `undefined` exploratory test only had 2/15 !s/line, much less crazy. Let me repeat the most insane part:

      equals(null == false, false, "!!");
      equals(null >= false, true, "!!!");
      equals(null <= false, true, "!!!");

I’ve basically given up on comprehension of this particular behavior and just settled for explanation and documentation instead.

So, what’s the point? Am I just picking on poor little old JavaScript? Partly, but my real aim is to document the myriad of strange and tantalizing (and infuriating) edge cases.

The moral of the story is to return `undefined` from methods where the result may be involved in a numeric comparison rather than null. Additionally `undefined` is the result returned by the empty function:

    equals((function(){})() === undefined, true);

so it’s more natural. The other recommendation is to always use the strict equality operator, it cuts out the most common weird edge cases. Tools like JSLint will point out situations where some subtle bugs can arise, use them!

The roller-coaster whirlwind-tour continues tomorrow with “The Crucible of Truthiness”. Stay tuned!

JavaScript: Hitting Bottom #1 – Constructors

Welcome to the first installment in an infinite series on JavaScript I like to call “Hitting Bottom”. JavaScript is an amazing language. Amazingly brutal and amazingly misunderstood. If you’re feeling “pretty confident” with your grasp on the JavaScript language then this series will destroy that confidence.

I was feeling pretty confident, I remembered feeling pretty confident about JavaScript a couple years ago too and having that confidence dashed upon learning more. Now that confidence is dashed again, but I’m building it up… slowly. And maybe I can bring you along with me this time, to spare you from waking up under an overpass on the information super highway, covered in CSS classes and your own vomit, pulling angle brackets out of your hair and scrounging around in your pocket for enough $() to purchase one more bottle of #B0053.

So, onwards.

Constructors, what are they? They are the functions that construct objects. Check it:

      equals({}.constructor, Object, "{}.constructor");
      equals([].constructor, Array, "[].constructor");
      equals(''.constructor, String, "''.constructor");
      equals(true.constructor, Boolean, "true.constructor");
      equals(false.constructor, Boolean, "false.constructor");
      equals((function(){}).constructor, Function, "anonymous function constructor");

Pretty cool. And if we were to make our own constructor JavaScript would be totally chill with that.

      function A() { }
      var a = new A();
      equals(a.constructor, A, "a.constructor");

That’s the wonderful thing about JavaScript, if you are doing regular things then everything works as expected.

      function B() { }
      var b = new B();
      equals(b.constructor, B, "b.constructor");
 
      B.prototype = new A();
      var b2 = new B();
 
      equals(b.constructor, B, "Constructor for existing object does not change after changing prototypes");
      equals(b2.constructor, A, "Constructor for new objects changes after changing prototypes");

So constructors are defined when the object is created, based on the prototype property inheritance chain. They don’t change for previously created objects when the prototype property changes, but newly created objects will have the new value for the constructor.

      function C() {}
      B.prototype = new C();
      var b3 = new B();
 
      equals(b3.constructor, C, "Constructor for new objects changes after changing prototypes again.");

It just keeps going deeper if you have more prototypes. Maybe there was like half a trick in there. Somehow I don’t think we’ve hit bottom yet.

JavaScript Hashtable for Objects

JavaScript…

there comes a time in every developer’s life when he wishes to be able to use a Hash in JavaScript like he can use a Hash in Ruby, you know, easily. This usually comes up when implementing A* or some other crazy graph search algorithm.

The problem: JavaScript objects make great Hashes for String and Number keys, but not for Object keys. Some QUnit tests highlight the problem readily.

    test("Hash sux?", function() {
      var x = {};
      var y = {name: "My Cool Object"};
      var barbazfoo = {name: "My Uncool Object"};
 
      x['a'] = true;
      x['b'] = true;
 
      equals(x['a'], true);
      equals(x['b'], true);
 
      x[y] = y.name;
      x[barbazfoo] = barbazfoo.name;
 
      equals(x[y], y.name); // Failed! y.toString == "[object Object]"
      equals(x[barbazfoo], barbazfoo.name);
    });

Now we have two options as I see it: download (or hand roll) our own Hashtable class that has even more akward syntax, worse performance and clocks in at 5k minified… or implement a toString() method that generates unique strings for each object (of types that we care about).

I opted for the second choice, after coming very close to choosing the first. Now if only there were some magical way to implement a unique toString method for all my objects that might want to end up as hash keys.

(function() {
    var id = 0;
 
    /*global GameObject */
    GameObject = function(game) {
      var self = {
        // Empty update by default
        update: function() {},
        click: function() {},
        objectId: '#Object:' + (id++),
        toString: function() {
          return self.objectId;
        }
      };
      return self;
    };
  })();

Gerta Rauss: So, we all agree that a closure is the best decision for all involved?

Juno MacGuff: SSHHIT! YES! Closure it up!

Now any GameObject can be used as a key to a hash, and as long as you aren’t going nuts and mixing and matching crazy strings as your keys you should have no collisions, or at least way fewer than 100%. Thanks a heap ‘[object Object]’!.

Recent Projects Recap

Just a quick round-up of some recent projects:

Fortress An online Dwarf Fortress style game demo. All open-source JavaScript with an MVC style framework. The dog walks around picking up plants. I guess the rubies are seeds or something. Not really playable yet, but under highly active development.

Pixie JavaScript pixel editor. Added color pallette selection and loading images from server.

Cask of Amontillado Not a recent project, or even any real development on it recently, but an oldie and a goodie.

Now is the time for our first reader survey:

How did you hear about STRd6? (Please answer in the comments.)

Can’t dup NilClass… maybe try `unloadable`

If you’re using a model or controller from an engine in Rails 2.3.2 you may encounter some crazy errors from time to time. Errors like: A copy of ApplicationController has been removed from the module tree but is still active! Or sometimes the even weirder one: can't dup NilClass

In one situation where you get A copy of ApplicationController has been removed from the module tree but is still active! it could be because you’re using a plugin or engine that provides controllers and inherits from ApplicationController. Some of the classes inherited or included in your engine controllers may fail to get unloaded and cause trouble after the first request to your system. Add unloadable inside your controller classes in your engine.

The can't dup NilClass error really tricked me though. It seemed to be saying something about duping nil class but not really. It was a lie! Well, almost. See, I had a model in my engine like this:

class Account < ActiveRecord::Base
  include Authentication::ByCookieToken
  include Authentication::AccountBuddy
 
  has_many :logins, :dependent => :destroy
 
  attr_accessible :nickname, :email

And I had a module in my app (not in the engine) like this (sort of a reverse-micro-plugin):

module Authentication
  module AccountBuddy
    def self.included(account)
      account.class_eval do
        has_many :characters
      end
    end
  end
end

And when I tried to access account.characters it was all “can’t dup NilClass”. But what it really meant to say was: “I’m returning nil instead of an array containing the characters belonging to this account because I became confused during the loading and unloading of all your crazy ass models. -Love, Rails”

So adding a little unloadable also fixes that.

class Account < ActiveRecord::Base
  unloadable # <= That's the ticket!
  include Authentication::ByCookieToken
  include Authentication::AccountBuddy # reverse-micro-plugin 
 
  has_many :logins, :dependent => :destroy
 
  attr_accessible :nickname, :email

What a load off.

A better way

Courtesy of Paul (from the comments)

unloadable is now deprecated, I think. As far as I am aware, the “right” way to do this is one of the following:

First, you could put something like this in your plugin’s init.rb file:

# This plugin should be reloaded in development mode.
if RAILS_ENV == 'development'
  ActiveSupport::Dependencies.load_once_paths.reject!{|x| x =~ /^#{Regexp.escape(File.dirname(__FILE__))}/}
end

Second, you could put something like this in your application’s environment.rb file:

config.reload_plugins = true if RAILS_ENV == ‘development’

If the above did not solve your problem:

Courtesy of Evan Owen (from the comments)

Another possible cause of this problem is that ActiveRecord also defines self.included. In order to ensure that ActiveRecord gets the call and can finish loading the model, a call to super needs to be added to the end of self.included like so:

def self.included(account)
  account.class_eval do
    has_many :characters
  end
 
  super # fixes the "can’t dup nil" issue
end

This did not work in my specific case, but may be the correct solution if you are suffering from a similar but different problem.

Adding a Non-null Column with no Default Value in a Rails Migration

This is something that I’ve often needed to do: add a new column to the DB that has a non-null constraint, but also doesn’t have a default value. There are a some options:

  • Forget the DB constraint and use `validates_presence_of` in the model
  • Add a default value for the new column with non-null and then remove the default
  • Add the column without a default value, then alter it to be non-null

The first method of simply using `validates_presence_of` won’t cut it for me because that doesn’t actually make guarantees on the data stored in the DB from interfaces outside the of application.

Adding the new non-null column with a default value and then altering it to remove the default would probably be the best choice if you just need a standard value for all your historic data.

The third method is how I did it, and I like it best for any data that can be computed to a reasonable value to start out.Here’s the source for my migration:

class AddLoginMetricsToAccounts &lt; ActiveRecord::Migration
  def self.up
    add_column :accounts, :last_login, :datetime
    add_column :accounts, :total_logins, :integer, :null => false, :default => 1
 
    Account.reset_column_information
 
    Account.all.each do |account|
      account.last_login = account.created_at
      account.save!
    end
 
    change_column :accounts, :last_login, :datetime, :null => false
  end
 
  def self.down
    remove_column :accounts, :total_logins
    remove_column :accounts, :last_login
  end
end

I’m adding a last_login column that I want to be non-null, but because it has no default value most DBs won’t allow the new column to be added (it violates data integrity). So the thing is to add the column without a a non-null constraint, populate it with acceptable values, and then to change the column to include the constraint.

Hope this comes in handy!

Pixie – A JavaScript Pixel Editor

As part of this amazing new game that we are working on we have an online pixel editor component. Right now it is a rough proof of concept. The primary goal is to create a simple online editor that provides the right blend of tools to easily create 32×32 pixel images which can then be saved locally or uploaded to the server. You can even load previously uploaded images, sweet!

The inspiration is Pixen, but instead of being Mac-only it will be available online for all platforms. Pixen provides a strong tool set and a great interface, but why be so exclusive about it? I know, right? The browser is the future anyway, and doesn’t crash as often.

Check out Pixie here. The idea is to keep it simple, there are only a few features missing from fullfilling every one of my wildest dreams (undo, selection, semi-transparency). For fun check out the JS code, it was designed with clarity and extensibility in mind. It’s a purely JS/CSS based editor, built using Prototype.js.

Editing images is fun!

Editing images is fun!

To get the images to the server they undergo an amazing (and probably inefficient) journey. Each pixel is read from the “canvas” and put into an ancient (late 90s) JS PNG encoder. That PNG encoder then spits out the image as a png data file which is then base64 encoded and sent to the server. The server base64 decodes the file and saves it to the local file system. Loading images from the server makes it even crazier! Since this ancient PNG encoder doesn’t load PNG data (to my knowledge) the server uses RMagick to read the uploaded image’s pixels and convert them to a JS array of hex color values, then passes that array into a load method back on the client. It’s amazing!

Have fun editing all those little images, and you can even check out the game that goes with it!

Ruby Quiz

So, better late than never I guess… I’ve been Ruby Quizmaster for about two months now.

The Ruby Quiz site is at http://rubyquiz.strd6.com. This is the third incarnation of Ruby Quiz, a weekly quiz that let’s you put your Ruby skills to the test. The first quiz was started by James Edward Grey II, there was also a book Best of Ruby Quiz (Pragmatic Programmers).

Great for keeping your skills of a programmer sharp! Also, there is a submission form for ideas. Please do submit ideas, I’m running out! The more to choose from, the better the quizzes!