Understanding JavaScript Object System

, , …,

This page is a in-depth tutorial on JavaScript objects. You should have some basic experience with JavaScript. If not, see: JavaScript Basics by Example.

JavaScript's object model is very different from class/object model in {Java, Python, Ruby, …}. To understand JavaScript's object, you need to throw away what you know about object oriented programing in those languages.

One simple way to think of JavaScript object is a hash table (aka “dictionary”, “associative list”). Each object always inherit parent object's key/value pairs, and the value of a key can be a function. This is in fact, the definition of JavaScript objects — a list of key/value pairs. JavaScript's object system is called prototype-based object system.

Let's begin with a summary of main concepts of JavaScript's object.

Here's a summary of object's properties.

Following are details.

What's a Object

A object in JavaScript is a set of unordered key/value pairs.

Technically, a object in JavaScript is any value that is not a {string, number (NaN, Infinity) , true, false, null, undefined}. For example, {Array, Function, Date, Regex, …, {…}, Object.create(…)} are all objects.

Arrays, functions, date, regex, …, are specialized objects. They have special properties and behaviors than normal objects. (they still are key/value pairs.)

For detail, see: What's Object in JavaScript?

Different Types of Objects: Native, Hosted, Own

There are different kind of objects.

Object Attributes

Each object has 3 associated info called attributes:

These “attributes” are not object properties, and there's no systematic way to read or set them. Some have special ways for you to read or write to, not all.

Attribute “prototype” ↔ Inheritance

The prototype attribute specifies a object's parent object. Object inherits the properties of its parent. If object B's prototype is object A, then B inherit all properties of A. This forms a inheritance chain called prototype chain.

For detail, see: Understanding Prototype & Inheritance.

Attribute “extensible”

The “extensible attribute” specifies whether properties can be added to the object.

For detail, see: JavaScript: Object Extensible and Prevent Modification

Attribute “class”

The class attribute is a string. By definition, it is the second part of the string returned when you call Object.prototype.toString(obj). For example, user-defined objects have class attribute of "Object". The class attribute is almost useless.

For detail, see: JavaScript Class Attribute.

3 Ways to Create Object

There are 3 ways to create object:

  1. Literal expression: {…} → Most useful, when you want to use a object as a hash table as data.
  2. Object.create() → Most power & flexible way to create object, because you can specify parent object, properties, property attributes, all in one place.
  3. Keyword new, in new function name() → complex behavior. Most useful when you are writing a object-oriented library. For some native objects, such as Date, it's the only way to create it.

For detail, see:

Note: technically, function, array, are also objects. So, when you define a function (⁖ function f(…){…}) or create a array (⁖ ar = [7,2,4]), you are also creating objects. Because they are objects, they can also have arbitrary properties. (⁖ ar = [7,2,4]; ar.p1 = 8;)

Own Property vs Inherited Property

There are 2 important distinction of properties.

This is the most important thing about properties. The behavior of many operations on properties, such as {accessing, setting, deleting, for … in loop, checking existence, …}, depend on whether the property is the object's own property.

For detail, see: JavaScript: Checking Property Existence

Creating Properties

Properties can be created at the same time when you create a object.

New properties can be added to a existing object by:

// adding a new property

// creating object with property "p1" and "p2"
var obj = {"p1":1, "p2":2};

// adding a property
obj["p3"] = 3;

console.log( obj );             // { p1: 1, p2: 2, p3: 3 }
// example of using Object.defineProperty();
var cc = {};
Object.defineProperty(cc, "pp", { value : 3});
console.log(cc["pp"]);          // 3

Deleting a Property

Use delete obj["property name"] to delete a property.

// example of deleting a property
var oo = {"p1":1, "p2":2};
delete oo["p1"];
console.log(oo);                // { p2: 2 }

Accessing Property: Dot Notation and Bracket Notation

There are 2 syntax to access a object's property:

// dot notation and bracket notation for accessing property

var x = {"b":8};    // creating object with property "b"

// dot notation
console.log( x.b );             // 8

// bracket notation
console.log( x["b"] );          // 8

Property name are strings. Values can be any type (string, number, function, object, …).

For detail, see: JavaScript: Dot Notation vs Bracket Notation

Property and Prototype Chain

Reading Property Traces Prototype Chain

When a property of a object is looked up (⁖ myobj["color"]), JavaScript first look at the object to see if it has that property, if not, it lookup its parent, and repeat, until a property is found or the root object Object.prototype is reached.

// accessing property goes up the prototype chain

var o1 = {"p1":1};

// create object o2, with o1 as parent
var o2 = Object.create(o1);

console.log(o2["p1"]);          // 1 , from o1
// accessing property goes up the prototype chain

var o1 = {};
console.log(o1["toString"]);    // [Function: toString]
// the property toString exists, it's from the prototype chain
// accessing property goes up the prototype chain

var gg = [3,4];                 // array
console.log(gg["toString"]);    // [Function: toString]
// the property toString exists, it's from the prototype chain

Setting Property Does Not Touch Prototype Chain

When you set a property, it does not touch the prototype chain. If the object has the property, its value is modified. If the object does not have the property, it's created for the current object.

// setting a property will not touch prototype chain.

var bb = {"p1":1};

// bb inherited the property named toString 
console.log("toString" in bb);              // true
console.log(bb["toString"]);                // [Function: toString]
console.log(bb.hasOwnProperty("toString")); // false

// set the property named toString
bb["toString"] = 2;
console.log(bb["toString"]);                // 2
console.log(bb.hasOwnProperty("toString")); // true

There are many JavaScript {operator, statement, method}, that {access, set, list, loop} properties. Some traverse the prototype chain, some doesn't, and some depend on whether the enumerable attribute of the property is true. Here's a summary: JavaScript: Property, Prototype Chain, Enumerable: Accessing & Listing Properties

Property's Attributes: writable, enumerable, configurable

Each property has 3 associated info called attributes. They are:

Their values are true or false.

In general, you can read or modify these attributes, by using:

For detail, see: JavaScript Property's Attributes: Writable, Enumerable, Configurable

Getter & Setter Properties

A special kind of property is called “getter” & “setter” properties. Normally, the value of a property is static. There's a way in JavaScript to make a property compute a value at the time the property is accessed. Such property is called “getter” property. (for example, each time user do myObj.color, and the return value can be different.)

Similarly, a setter property is a special preperty that computes a value whenever user sets the property. For example when user writes myObj.color = "red", and a function will be called and take the input "red" and convert to some color value then set to myObj.color.

For detail, see: JavaScript: Getter and Setter Properties Tutorial

Reference

blog comments powered by Disqus