There is no magic in programming languages. The fact that they are formal languages makes them deterministic. For every behaviour there is a reason. For every error there is a logical cause.

Before googling for an odd error message, try to understand what the interpreter means. This is the fastest way to solve the problem.

I often see developers wondering why a certain test throws an error, whilst reading several times the production code, without really understand what’s the meaning of the error. Wrong approach, one must know what the interpreter is saying before searching for the cause. It may be an error in the test itself!

The same error message may be expressed in a different manner by different browsers and other JavaScript interpreters like Node. This fact emphasizes the need for understanding what are they talking about.

In order to understand JavaScript error messages one must understand
what’s the meaning of “undefined”. Undefined is a special value.

var x; // We are declaring a varible, whose value is undefined

In this case we say that variable “x” is undefined, is the type of the variable:

typeof(x); // prints out the string "undefined" (as a string!).

The value of a variable is undefined until it’s assigned a concrete
value:

var x = 5; // x is a Number
var x = function(){}; // x is a Function
var x = {}; // x is an Object
var x = true; // x is a boolean
var x = undefined; // x is undefined

Now let’s review errors containing the word “undefined” in the message:

TypeError: undefined is not a function (Google Chrome)

The interpreter says that something used as a function, is not a function actually, it’s an undefined variable. Why does the interpreter assumes it’s a function? Because there are braces after a name. When there is an open parenthesis right after a name, the interpreter determines that name is a function according to the grammar of the language. It’s exactly like the question mark at the end of a sentence in English, we assume the sentence must be a question because of the mark at the end. The writer of the function was probably expecting the variable to be a function at that point but given some defect, it’s not. This is how to reproduce the error:

var x; // x is undefined.
x(); // and... undefined is not a function, is just undefined!

TypeError: Cannot read property ‘length’ of undefined (Google Chrome)

The error says there is a property named “length”. A property is a member of an object. The interpreter assumes that “length” must be a property of an object because there is a dot preceding it. Properties are accessed with a dot:

var obj = {propA: 123, propB: 456}; // an object with 2 properties
var val1 = obj.propA; // reading property (123)
var val2 = obj.propB; // reading property (456)

The error message says that the variable at the left of the “length” property is undefined, that is, the object is not actually an object, it’s actually the undefined value. This is the way to reproduce the error:

var obj; // obj is undefined
obj.length; // trying to create or reference a property in an undefined value, raises an error.

If the “property” is accessed to set it a value, the error message will be slightly different:

obj.length = 777; // TypeError: Cannot set property 'length' of undefined

TypeError: Cannot call method ‘trigger’ of undefined (Google Chrome)

This one is similar to the previous. It says “of undefined” expresses the sense of belonging. It must be related to an object. This time it’s a method, not a property. It assumes that it must be a method because there are braces after “trigger”. The error means that the value of the variable at the left hand side of the dot, is undefined:

var obj;
obj.trigger(); // trying to reference a method in an undefined value, raises error.

Node.js produces slightly different messages for the same errors:

var x; // variable x is undefined
x(); // TypeError: Property 'x' of object #<Object> is not a function

In JavaScript everything happens within a certain environment. When the variable is defined out of any function its scope is global. In the case of the browser, the global environment is the “window” object. In the case of node, it’s the “global” object:

var x = 5;
window.x; // 5 in the browser, error in node
global.x; // 5 in node, error in browser

Node makes this fact explicit in the error messages.

TypeError: Property ‘x’ of object #<Object> is not a function (Node.js)

As there is not dot preceeding the “x”, we know it’s talking about
the “global” object. As we are using braces after “x”, node assumes
it must be a function. Notice that it doesn’t reveal the value of “x”, which is undefined, it just says that “x” is not a function. So it would raise the same error if “x” was a number.

At the time of this writing, Firefox behaves a bit similar with regards to the value of the variable:

TypeError: x is not a function (Mozilla Firefox)

var x;
x(); // TypeError: x is not a function

ReferenceError: x is not defined

I find this message a bit unfortunate. I would prefer “x is not declared” or “x does not exists”. Because “not defined” seems to be the same as “undefined” but it’s not. This error happens when the variable has not been declared but it’s value is being accessed:

var x = 10 + someNameNotDeclaredEver; // ReferenceError