Search code examples
javascriptobjectnullprototype-programming

using null as an expected object


The value null represents the intentional absence of any object value.

In APIs, null is often retrieved in place where an object can be expected but no object is relevant.

MDN (emphasis mine)

TL;DR: Why does null.content throw an error but false.content returns undefined?

In my project’s API, I have methods allowing the user to set and get an icon of a Page.

Page.prototype.setIcon = function (key) {
  this.icon = database.find(function (item) { return item.content === key })
}
Page.prototype.getIconContent = function () {
  return this.icon.content
}

A string is given as the argument, and the program searches the database for an object whose content property equals the given argument. If no such object is found, the find() function will return undefined. So this.icon will be set to undefined.

This is not good because when the user calls getIconContent(), they will receive an error, because the program is trying to find the content property of undefined.

What I want to happen is that if no such object in the database is found, setIcon() will set this.icon to a falsy value that will not throw an error when attempting to get the content property. So I tried using OR null, as it is an object.

Page.prototype.setIcon = function (key) {
  this.icon = database.find(function (item) { return item.content === key }) || null
}

But this didn’t work because trying to get null.content will still throw an error. So then I tried OR false and it works the way I want.

Page.prototype.setIcon = function (key) {
  this.icon = database.find(function (item) { return item.content === key }) || false
}

So when a user calls setIcon() with no argument, and then tries getIconContent(), they will not receive an error, because false.content doesn’t throw an error; it returns undefined, which is the behavior I’m looking for.

My question is, why is false the correct usage, when clearly the expected type of icon should be an object? I would think null would be more “semantically correct,” but it throws an error.


PS: In addition to false, these are other falsy values that don’t throw errors:

var a = 0;   a.content // returns `undefined`
var b = NaN; b.content // returns `undefined`
var c = '';  c.content // returns `undefined`

The empty object {}, even though it is truthy

var d = {}; d.content // returns `undefined`

undefined throws an error as expected

var e; e.content // throws an error "Uncaught ReferenceError: e is not defined"

Solution

  • false is a boolean. Booleans are boxable (like numbers and strings) because there is a Boolean constructor in the language. When you try to access false.content, it becomes an object, nearly (but not quite, because it's still of type "boolean") what you'd get from new Boolean(false). Being an object, it can have properties. It's just that booleans have no useful properties (unlike strings which have length etc) so you never see them used that way.

    On the other hand, there is no Null constructor that could box the value null of type "null" (or indeed type "object" in older versions of ECMAScript). So there is no valid way to interpret null.content.