23
May 2011

JavaScript - Everything Acts Like An Object Except Null and Undefined

JavaScript Garden

Object Usage and Properties
Everything in JavaScript acts like an object, with the only two exceptions being null and undefined.
false.toString() // 'false'
[1, 2, 3].toString(); // '1,2,3'

function Foo(){}
Foo.bar = 1;
Foo.bar; // 1

A common misconception is that number literals cannot be used as objects. That is because a flaw in JavaScript’s parser tries to parse the dot notation on a number as a floating point literal.
2.toString(); // raises SyntaxError

There are a couple of workarounds which can be used in order make number literals act as objects too.
2..toString(); // the second point is correctly recognized
2 .toString(); // note the space left to the dot
(2).toString(); // 2 is evaluated first

Objects as a Data Type
Objects in JavaScript can also be used as a Hashmap, they mainly consist of named properties mapping to values.

Using a object literal - {} notation - it is possible to create a plain object. This new object inherits from Object.prototype and has no own properties defined on it.
var foo = {}; // a new empty object

// a new object with a property called 'test' with value 12
var bar = {test: 12};

Accessing Properties

The properties of an object can be accessed in two ways, via either the dot notation, or the square bracket notation.
var foo = {name: 'Kitten'}
foo.name; // kitten
foo['name']; // kitten

var get = 'name';
foo[get]; // kitten

foo.1234; // SyntaxError
foo['1234']; // works

Both notations are identical in their workings, with the only difference being that the square bracket notation allows for dynamic setting of properties, as well as the use of property names that would otherwise lead to a syntax error.
Deleting Properties
The only way to actually remove a property from an object is to use the delete operator; setting the property to undefined or null only remove the value associated with the property, but not the key.

var obj = {
bar: 1,
foo: 2,
baz: 3
};
obj.bar = undefined;
obj.foo = null;
delete obj.baz;

for(var i in obj) {
if (obj.hasOwnProperty(i)) {
console.log(i, '' + obj[i]);
}
}

The above outputs both bar undefined and foo null - only baz was removed and is therefore missing from the output.
Notation of Keys
var test = {
'case': 'I am a keyword so I must be notated as a string',
delete: 'I am a keyword too so me' // raises SyntaxError
};

Object properties can be both notated as plain characters and as strings. Due to another mis-design in JavaScript’s parser, the above will throw a SyntaxError prior to ECMAScript 5.
This error arises from the fact that delete is a keyword; therefore, it must be notated as a string literal to ensure that it will be correctly interpreted by older JavaScript engines.
The Prototype

JavaScript does not feature a classical inheritance model, instead it uses a prototypal one.
While this is often considered to be one of JavaScript’s weaknesses, the prototypal inheritance model is in fact more powerful than the classic model. It is for example fairly trivial to build a classic model on top of it, while the other way around is a far more difficult task.
Due to the fact that JavaScript is basically the only widely used language that features prototypal inheritance, it takes some time to adjust to the differences between the two models.
The first major difference is that inheritance in JavaScript is done by using so called prototype chains.
Note: Simply using Bar.prototype = Foo.prototype will result in both objects sharing the same prototype. Therefore, changes to either object’s prototype will affect the prototype of the other as well, which in most cases is not the desired effect.

function Foo() {
this.value = 42;
}
Foo.prototype = {
method: function() {}
};

function Bar() {}

// Set Bar's prototype to a new instance of Foo
Bar.prototype = new Foo();
Bar.prototype.foo = 'Hello World';

// Make sure to list Bar as the actual constructor
Bar.prototype.constructor = Bar;

var test = new Bar() // create a new bar instance

// The resulting prototype chain
test [instance of Bar]
Bar.prototype [instance of Foo]
{ foo: 'Hello World' }
Foo.prototype
{ method: ... }
Object.prototype
{ toString: ... /* etc. */ }

In the above, the object test will inherit from both Bar.prototype and Foo.prototype; hence, it will have access to the function method that was defined on Foo. It will also have access to the property value of the one Foo instance that is its prototype. It is important to note that new Bar() does not create a new Foo instance, but reuses the one assigned to its prototype; thus, all Bar instances will share the same value property.

Note: Do not use Bar.prototype = Foo, since it will not point to the prototype of Foo but rather to the function object Foo. So the prototype chain will go over Function.prototype and not Foo.prototype; therefore, method will not be on the prototype chain.

Read More Here.