JavaScript Objects
https://www.dofactory.com/javascript/objects
avaScript Objects
Creating objects with object literals
A JavaScript object is a collection of properties where each property has a name and a value, similar to Hash, Map, or Dictionary in other languages. The name of a property can be any string, including an empty string. The value can be any value, such as a string, Boolean, number, and null, but it cannot be undefined. The object's properties can be defined even after you start using the object. But first, let's look at how we create objects in JavaScript.
The easiest way is to create a new object is with object literal notation which is bracketed by a pair of curly braces: {}. Properties and their values can be added as you go. In the example below we create an empty object, using object literal notation, and we are adding two properties after that:
Run
As an alternative you can immediately assign properties and their values in the literal notation.
Run
JavaScript objects are mutable, meaning you can modify their values.
Run
Property values are not limited to primitive types, like number or string; you can also add properties that are other objects, including functions. When a function is added to an object it is called a method.
Run
You can define objects and all their member properties and methods in a single statement as object literal. Below we create a rectangle with two numeric properties, one object property, and a method.
Object properties
In this section we look at accessing, retrieving, and deleting object properties.
Accessing properties
Property values can be retrieved in one of two ways; dot notation and bracket notation. Below are examples of each:
Run
Dot notation is used more often because it is easier to read and more compact. So when would you use bracket notation? Square brackets allow you to use property names that are not valid identifiers and don't work with dot notation, for example when they have spaces in them or start with a number. Also, bracket notation allows you to use property names that are variables. Examples of both are below:
Run
The last two statements are included to demonstrate that dot notation does not work with the property being a variable.
Getting property names with for-in
To get a list of property names from an object use the for-in loop.
Run
The for-in loop returns all members of the object, that is, all properties and methods. If you don't need certain members or data types, you can exclude these from enumeration using the typeof operator. In the example below we skip functions.
Run
Be aware that the order in which the properties are returned by a for-in loop is not guaranteed. If order is important you will need to manage your own list of properties (probably as an internal array).
deleting properties
Use the delete operator to remove a property from an object, like so:
Run
Creating objects with constructor functions
Object literal notation, such as var x = {}, is preferred if all you need is a single object and there is no need for multiple instances. However, if you need multiple instances, it is better to use a constructor function. Here is an example of a book constructor function.
Properties, including methods, are assigned to the 'this' value in the function's body. In the above example a property and a function are assigned. Also notice that this function is capitalized (i.e. Book); constructor functions are capitalized by convention in JavaScript
To create a new object with this function you use the new operator followed by a function invocation. A function that is invoked this way is called a constructor function whose main purpose is to create and initialize a new object. Here we are creating a new book object:
Run
When new Book() is invoked, JavaScript creates a new empty Object and sets an internal property which specifies that the new object's prototype is Book, that is, the newly created object inherits the prototype of the function. It then passes the Book() function two arguments: the new object as this (as a hidden parameter) and the "901-3865" as isbn. The function, in turn, sets the object's isbn property to "901-3865" and also adds the getIsbn() method to the object. JavaScript returns the newly created object to the caller which then assigns the new object to the book variable.
Each time you invoke new Book(), a new getIsbn method is created which is a rather inefficient because the method is the same for all book instances. A better approach is to let all instances share a single method which can be accomplished by adding getIsbn to the prototype of Book rather than the Book function itself. Here is how this is done:
Run
As you can see, it works the same as when getIsbn was not shared. This is a very common object creation pattern. To really get to know JavaScript, we present this pattern and many others in our unique JavaScript + jQuery Design Pattern Framework. Click here for more information.
Omitting new
If you forget to use the new keyword, your code will break without warning. There won't be any compile-time or runtime warnings. See the example below where we call the instructor function with new and later without new.
Run
Calling a constructor function without new is like calling an ordinary function. The this value in this call will not be bound to a new object. Instead, it is bound to the global object. Notice that the function is adding the message property to the global object (i.e. window). This is often referred to as polluting the global namespace.
You can protect yourself against this mistake by including a check at the beginning of each constructor function. Essentially, it checks if this is an instance of Task: if it is not, then it invokes new Task() returning a true new instance.
Run
To learn more about avoiding common JavaScript errors, the JavaScript + jQuery Design Pattern Framework includes helpful guidelines about optimal object instantiation, object scopes, and object lifetimes through the use of design patterns and best practices. To learn more click here.
The value of this
In JavaScript, the this keyword provides objects a way to identify and examine themselves. Consider the example below:
Run
We have two circles, a small one and a large one. Each knows the size of their radius because in the getRadius method this value refers to the object it called from.
However, this can refer to a different object as well; it all depends on the execution context. All JavaScript code runs in an execution context. You can imagine the execution context as the scope of a function. A call to a function creates a new execution context. Also, in recursive functions a new context is created each time a function makes a call to itself.
Code that is not inside a function executes in a global execution context in which this is bound to the global object. The example below shows that in the global context the str variable is the same as this.str.
Run
The value of this inside a function body is determined how the function is invoked. The context is commonly furnished by the parent scope in which the function was invoked. Consider the example below:
Run
When invoking circle.getRadius() JavaScript establishes an execution context for the function call and sets this to the circle object. anotherCircle does not have a getRadius() method, but can be copied from circle. Once copied and executed, the value of this refers to anotherCircle which is why the first alert, which tests for cicle, return false, because this is not of type circle.
There is an easy way to determine the value of 'this' in a function. Look at the immediate left side of the invocation parentheses () and determine the object to which it belongs to. Let's explain this with an example. Below we have three names with different scope. The First name has global scope and is a property of the global object, the Middle name is a student object property and the Last name is a detail object property.
Run
In the first example, the left side of the parentheses is the variable result which belongs to the global object when invoked. So we get its name which is 'First'.
The second example, the left side of the parentheses is getName, which belongs to the detail object, so we get its name which is 'Last'.
Prototypal inheritance
Unlike classical inheritance where classes inherit from classes, JavaScript objects inherit from other objects, called prototypes, in a prototypal inheritance system.
Each object in JavaScript has a prototype property that points to a prototype object. There is nothing special about prototype objects, they are regular objects. Objects inherit all properties and methods that are available on the prototype object. Prototype objects themselves have prototypes, which leads to a prototype chain. This process in which objects inherit properties from objects in a prototype chain is referred to as prototypal inheritance. This model is simpler, smaller, and with less redundancy than that of classical inheritance.
Prototypal inheritance works on the concept of differential inheritance in which each item in the prototype chain only augments the differences with its parent. In other words, properties on prototype objects do not change or override properties in the parent object.
Let's look at an example. First, we create an account object with a bank property and a getBank method. This object will serve as the prototype for other objects like savings, checking, etc.
Setting prototypes to an object is done by setting an object's prototype attribute to a prototype object. We can make this process a bit simpler by using a helper function, so let's first create this function; we'll name it createObject. What follows may seem a bit convoluted, but once you understand prototypes in JavaScript things will clear up. Furthermore, our JavaScript + jQuery Design Pattern Framework does a wonderful job of explaining the details of prototypal inheritance which will help you in your journey to becoming a true JavaScript rockstar. To learn more about this framework click here. But now back to createObject.
createObject accepts a prototype object as an argument, named p and returns a new object (a function object really) whose prototype attribute is set to the passed in prototype object. The prototype attribute is how JavaScript is able to follow an object's prototype chain.
With this function in place, we now like to create a savings object that inherits the functionality of the account object. First, we call our createObject function and pass in the account. This returns a new object with account as its prototype. Next we add member properties and methods that are specific to savings accounts.
Run
After creating the savings account, we add a couple of account holders to the object. Next we see which bank is associated with these savings accounts; as expected it is "Bank of America". In the second to last statement we change the bank to "JP Morgan Chase", which is confirmed with the alert message. This confirms that the prototypal inheritance chain works as expected.
Building prototypal hierarchies
You can inherit from savings and add new properties and methods to a new parent object, and do this again and again. Inheritance can go many levels deep, but in order to not overcomplicate things, it is generally best to limit this to 2 or 3 levels. Of course, JavaScript will just continue searching the prototype chain until it hits the last object, the global object, and if the property or methods is not found, JavaScript return undefined. Lengthy inheritance chains will negatively affect performance, which is another reason to avoid deep hierarchies.
Prototypal inheritance is a highly memory efficient. A prototype is just a single object and derived object instances hold only references to their prototype. All replicated instances share a single copy of the members defined in the prototype object.
If you are coding to the EcmaScript 5 specification, then you don't need to write the aforementioned createObject function yourself. EcmaScript 5 has a built-in Object.create() method, which allows the creation of derived objects just as we did with our own createObject. Here is the code:
Run
If you are an experienced object-oriented developer you know that programming a class-based language is impossible without understanding class based inheritance. Similarly, writing professional JavaScript requires a solid grasp of prototypal inheritance to be able to move beyond the simple JavaScript snippets that were common just a few years ago.
Our unique JavaScript + jQuery Design Pattern Framework provides the necessary information on prototypes and how to use these in your own projects by applying proven design patterns and best practices. Click here for more details.
Once you are familiar with prototypal inheritance it is actually easier to work with than classical inheritance. Its syntax is more tidy and simple. To customize your objects, you can quickly modify properties and methods at runtime without requiring a large amount of infrastructure code.
Last updated