Course: JavaScript

Progress (0%)

  1. Foundation

  2. Numbers

  3. Strings

  4. Conditions

  5. Loops

  6. Arrays

  7. Functions

  8. Objects

  9. Exceptions

  10. HTML DOM

  11. CSSOM

  12. Events

  13. Drag and Drop

  14. opt Touch Events

  15. Misc

  16. Project: Analog Clock

JavaScript Objects - Basics

Chapter 36 45 mins

Learning outcomes:

  1. What are objects
  2. Object literal syntax
  3. Accessing properties
  4. Modifying, adding and removing properties
  5. The Object() constructor
  6. Reference passing
  7. Iterating over an object using for...in
  8. Comparing objects
  9. Checking for a given property

Introduction

Since its inception in 1995, JavaScript has been based around the idea of objects. The whole ecosystem of the language resolves around objects. Object are, by far, the most fundamental data type of JavaScript — they sit right at its core.

If anyone wants to become a proficient JavaScript developer, an in-depth knowledge of objects is paramount. One couldn't go far in JavaScript without knowing concepts such as prototypes, constructors, inheritance, and so on.

Uptil this point in this course, we have a very brief and general understanding of the rudimentary stuff related to objects i.e. what are properties, how to access them; what are methods and how to call them; what is this, and much more.

In this chapter, our aim is to consolidate all that we've learnt in regards to objects from previous chapters together with some more interesting concepts and thus get a complete overview of the basics of working and interacting with objects in JavaScript.

Let's begin!

What are objects?

Starting with the most fundamental idea of the most fundamental data type, let's see what exactly is meant by an 'object':

An object is an unordered collection of properties.

A property is simply a characteristic, a trait, of an object. It is mainly composed of two parts: a key and a value.

The key, also known as the property's name, defines the name of the property. The value on the otherhand simply specifies the value associated with this key. We say that an object's key 'maps' to a given value.

A property is often referred to as a key-value pair.

And, by that means, it won't be wrong to say that:

An object is an unordered collection of key-value pairs.

Coming back to the notion of a property in JavaScript, a property whose value is a function object is called a method. A method is, thus, simply a property that has a function as its value.

Simple!

So all this constitutes the basic theory of the very basics of objects. Let's now get a quick review of how to actually create objects in JavaScript and, in the meanwhile, put all of this discussion under the hood of actual code.

Object literals

Perhaps the most intuitive and simplest way to create an object in JavaScript is by using what's called the object literal syntax.

As the name suggests, it's the literal way to denote an object in source code.

Shown below is the syntax of an object literal:

{key1: value1, key2: value2, ..., keyN: valueN}

Inside a pair of curly braces ({}), we put the properties of the object, each denoted as a key: value pair, separated from the other using a comma (,).

In many programming languages, it's not possible to create an object in one line (or at least in one go) as is possible in JavaScript; thanks to the object literal syntax.

For instance, to create an object in Python, we have to set up a small boilerplate code to create a simple object.

In fact, the object literal notation of JavaScript is so intuitive and easy to understand that it is commonly used today as a data exchange format known as JSON. But that is a story for some other day...

However, there are other data structures in some programming languages that resemble this nature of objects in JavaScript.

For e.g. dictionary literals in Python look almost like JavaScript's object literals. PHP's associative arrays don't look like JavaScript object literals, but behave pretty much the same way in that they are key-value collections as well.

Anyways, a lot of talking, let's now create a simple object literal to represent a point on a 2D plane:

var point = { x: 0, y: 0 };

Here, point is an object with two properties: x denoting the x co-ordinate of the point and y denoting the y co-ordinate of the point, both currently set to 0, which corresponds to a point on the origin.

Now, let's retrieve the value of both these properties. Remember how to do this?

To retrieve a property's value in JavaScript, we could use either of two options: dot notation or bracket notation.

To access a property p on an object o using dot notation, we write the following expression:

o.p

Note that both o and p are identifiers in this expression, and therefore must obey rules governing identifier names (for e.g. there can't be a question mark in the name).

It's pretty clear from the expression above as to why do we term this notation as 'dot notation' — it's because there is the usage of the dot (.) character.

That simple!

Many programming languages, that supports objects, use this same dot notation to access properties on given objects — the notation is quite popular. Examples of these languages are Python, Java, C# etc.

In PHP, accessing a property on an object is done via ->.

Below we access both the properties x and y of the point object defined above:

var point = { x: 0, y: 0 };

console.log(point.x, point.y);
0 0

As you may know, points on a graph are typically represented inside a pair of parentheses (()) with the co-ordinates being separated by a comma (,), for e.g. (-1, 5). Let's output point in this format:

var point = { x: 0, y: 0 };

console.log('(' + point.x + ', ' + point.y + ')');
(0, 0)

In addition to dot notation, an object's property in JavaScript could also be accessed via the bracket notation. Many programming languages don't provide multiple notations for accessing an object's property — you'll find these features only in the world of JavaScript.

Here's how to access a property p on an object o:

o['p']

First comes the object whose property is to be accessed (akin to dot notation), and then follows a pair of square brackets ([]) within which we put a string containing the name of the property.

Once again as the name suggests, this notation employs brackets, hence it's called 'bracket notation'.

Bracket notation is useful when we want to access an object's property using the value of some variable or other property, or when the property's name has certain characters in it that would otherwise lead to a syntax error if accessed via dot notation.

Let's consider each of these uses of bracket notation one-by-one...

Below we create a variable name containing the string 'x' and then use this variable to access the property x of the point object:

var point = { x: 0, y: 0 };
var name = 'x';

console.log(point[name]);
0

Note that point[name] does NOT access the name property on point (that would've been accomplished using point.name). Instead, name is considered an expression whose ultimate value is used as the name of the property to access.

And so, we're not just limited to writing an identifier within the brackets — we could use any valid expression. That expression is evaluated, its result coerced into a string and then this string used as the name of the property to access.

Remember that, in bracket notation, the result of the expression inside the square brackets ([]) is converted into a string before the property is searched for, and consequently accessed in the object.

In the code below, we access the name property of the object lang using bracket notation, specifying the name by concatenating two strings 'na' and 'me' together:

var lang = {
   name: 'JavaScript',
   yearReleased: 1995
};

console.log(lang['na' + 'me']);
JavaScript

Moving on, let's now see the second use of bracket notation.

Often times, when wanting to access a property on a given object, the name of the property might not be a valid identifier name in JavaScript. This eliminates the choice of using dot notation to access the property, since doing so would lead to a syntax error.

Accessing such a property is only possible via bracket notation, as the property's name is specified as a string value, which could contain any character.

Consider the code below:

var lang = {
   name: 'JavaScript',
   yearReleased: 1995,
   'multi-paradigm': true
};

console.log(lang['multi-paradigm']);
true

We define a property multi-paradigm on lang and then retrieve it using lang['multi-paradigm']. This is necessary since the property's name contains a hyphen (-), which is invalid to be used in an identifier's name.

Below we try to access multi-paradigm via dot notation, and not surprisingly, get an error thrown:

var lang = {
   name: 'JavaScript',
   yearReleased: 1995,
   'multi-paradigm': true
};

console.log(lang.multi-paradigm);
Uncaught ReferenceError: paradigm is not defined at <anonymous>:7:24

However, it's imperative to understand that this error is not a syntax error arising because of using the invalid hyphen character in the property name multi-paradigm, by is rather a runtime error following the way the expression is interpreted.

What's happening over here is that lang.multi-paradigm is interpreted as a subtraction operation (denoted with the - symbol) where paradigm is subtracted from lang.multi (which returns undefined).

Since, paradigm doesn't exist, it throws a reference error.

The code above doesn't throw a syntax error.

Modifying, adding and removing properties

When we are creating an object using the literal syntax, we are not bound to adding all the desired properties right at this stage — they could be added later on.

Once an object gets created in memory, we could very easily modify, add and/or remove given properties from it. Doing so is again possible using either of the two notations: dot and bracket.

However, this time (except for when deleting a property) an assignment syntax ought to follow the notation, that specifies the new value to put into the property.

So, for example, if we have an object o with a property p and want to change it to some other value newValue, we'd use the following:

// dot notation
o.p = newValue;
// bracket notation
o['p'] = newValue;

This assignment works exactly like that for variables — there's absolutely no difference.

Both the statements shown above are expression statements i.e. they are expressions, akin to variable assignment statements.

Let's consider an example.

Below, we have our previous point object in place with its two properties x and y. We log the value of point.x, then change its value in line 3 and finally log it again:

var point = { x: 0, y: 0 };

console.log('Before change:', point.x);

point.x = 10;

console.log('After change:', point.x);
Before change: 0
After change: 10

As can be seen, the property's value is changed to 10 after the assignment statement in line 5.

Moving on, now that we know how to modify a property's value, adding a new property to an object won't be any difficult to understand.

Essentially, when assigning a value to a property, if the property already exists on the object, it's merely modified. However, if no such property exists, a new property is added to the object with the provided value.

Consider the code below, where we add a third property z to the object point, to represent the point in 3D space:

var point = { x: 0, y: 0 };

// add a new property z
point.z = 0;

console.log(point);
{x: 0, y: 0, z: 0}

Note that before adding a property to 'something', make sure that the 'something' is actually an object. Otherwise, this would lead to an error.

Take a look at the code below:

var point;

// add a new property x
point.x = 0;

console.log(point);

Line 4 throws an error since point is not an object — it's undefined — and we are trying to add a property to it, which is only possible on an object (or better to say, not possible on undefined at least).

In order to make this code work, we must make point an object prior to the property access statement.

The simplest way to do so is to create an empty object literal and assign it to point.

This is illustrated as follows:

var point = {};

// add a new property x
point.x = 0;

console.log(point);
{x: 0}

Setting identifiers to empty object literals is not something you'd see occasionally in code snippets out there — it shows up quite frequently.

Moving on, often times it's required to remove a property from an object. In this regard, we use the delete keyword.

Let's see how to use it...

To remove a property p from an object o, we use the following:

// dot notation
delete o.p
// bracket notation
delete o['p']

The delete keyword denotes an expression, whose return value is true when the given property is successfully deleted from the given object, or else false.

Let's delete the newly-added z property from our old point object:

var point = { x: 0, y: 0 };

point.z = 0;
console.log('Before removal:', point.z);

console.log(delete point.z);
console.log('After removal:', point.z);
Before removal: 0
true
After removal: undefined

The second log where we output the return value of delete point.z, which is true, tells us that the deletion operation went successful.

Let's try deleting a predefined property from the global window object:

console.log(delete window.alert);
false

As can be seen, we get false returned which signals that the deletion operation wasn't successful. This is because all predefined properties on window are non-configurable i.e. they can't be deleted.

We'll see more on non-configurable properties in the next chapter on JavaScript Objects — Property Attributes.

Deleting a non-configurable property in non-strict mode, as we do above, returns false, whereas doing so in strict mode throws an error.

The Object() constructor

As with many data types in JavaScript, including numbers, strings, Booleans and arrays, there is a constructor way to create native objects. The constructor is called Object().

Here's how the constructor function looks:

Object([value])

value specifies the value to coerce into an object.

When invoked without an argument, Object() returns an empty object, similar to {}, as shown below:

var point = new Object();

console.log(point);
{}

The expression new Object(), where Object() is called as a constructor, is effectively the same as the expression Object(), where Object() is called as a function.

This is analogous to the Array() constructor — when it's called with new (i.e. new Array()) and when it's called without new (i.e. Array()), both invocations return exactly the same thing.

Constructors for primitive types such as Number(), String() and Boolean() yield different results based on the context of the invocation. For e.g. new String() returns a String object while String() returns the string primitive ''.

Constructors for objects usually have this characteristic. That is, it doesn't really matter whether we invoke them in the context of a constructor or in the context of a normal function — in either case an object is created and returned.

It's not always the case that constructors in JavaScript yield the same result when called without new or with new. For e.g. as we shall see in the chapter JavaScript Dates, calling new Date() returns a Date object while Date() returns a string primitive holding the current date.

So the code above is identical to the following:

var point = Object();

console.log(point);
{}

Moving on, let's add a couple of properties to this newly-created empty point object. There is essentially no difference between objects created literally or using Object() — all the underlying operations work the same way:

var point = new Object();

point.x = 0;
point.y = 0;

console.log(point);
{x: 0, y: 0}

So all this was simple, wasn't it?

Difference between {} and new Object()

Semantically (in terms of meaning), there is no difference between {} and Object().

But obviously, syntactically there is a difference — in fact, a big difference.

{} is shorter and doesn't involve a function invocation. On the contrary, new Object() is longer and involves a function invocation (and is, likewise, relatively slightly slower than {}).

In short, new Object() is not elegant and concise at all. Well, it's not even needed in any case!

There is absolutely no single reason to use new Object() in place of {} in code. It's not possible to create a new object in one single line solely using new Object().

To do so, we only have one option and that is to provide the object as a literal into the Object() constructor, which could just be simplified to using the literal directly (without passing it to new Object()).

What's the point of the Object() constructor?

At this point, there might be a question roaming around in your mind: 'What exactly is the point of the Object() constructor (or function)?'.

Hmm. This is a valid question.

Object is simply provided as a means to encapsulate properties and methods available to all objects in JavaScript and to provide static methods for common object-related functionality.

In any case, there had to be some object to contain all these utilities. And the most obvious name for this object was Object.

It is consistent with all other objects in JavaScript that contain utilities to be inherited by their instances i.e. Object is a function and contains a prototype property encapsulating all the methods to be inherited by any object in JavaScript (if it doesn't define the same method on its own).

This last statement answers the question as to why is Object() a function. Once again, reiterating over this idea, it's a function simply to use the same constructor function–prototype mechanism used by all other objects in JavaScript.

You'll understand all this much better once you understand constructors and prototypes in JavaScript.

Passing by reference

All the way back in the chapter JavaScript Foundation — Values and References, we learnt that objects in JavaScript are passed around in terms of their references.

This is an extremely important concept to be aware of. It can prevent many unexpected errors from creeping into our applications as we pass around objects.

Let's review what exactly is meant by 'pass by reference'.

When an object value is stored in a variable, what's actually inside the variable is a reference to some location in memory that contains the object.

As we pass around the variable to other places, for e.g. provide it as a function argument, or assign it to another variable, we might be tempted to think that we are passing around the actual object but that's just NOT the case — instead we are passing around the reference.

A reference in JavaScript is simply the address of a memory location.

JavaScript doesn't expose this reference to the end developer. That is, we can't figure out the exact reference to an object in memory, which is usually represented by some hexadecimal number in other programming languages.

Anyways, following from the fact that objects are passed around by their references and not by their actual values, if we make any change to the passed-on value, that change would be visible in actual object as well, and vice versa.

Consider the codde below:

var point = { x: 0, y: 0 };
var point2 = point;

point2.x = 10; // update point2's x property to 10

console.log(point.x);
console.log(point2.x);

First, we create a variable point and assign it an object literal. Next, we create a second variable point2 and assign it the point object. This statement is the essence of the code above.

In the end, we change the property x of point2 to the value 10 and then log both point.x and point2.x to see their respective values.

10
10

As is evident in the console snippet above, both point.x and point2.x are equal to 10.

But why?

Well, let's see it...

When we assign point to point2, as one might think, we aren't storing a new object inside point2 — rather, we are storing the reference, saved in point, inside point2.

Recall that objects are passed around by their references. That is, point holds a reference to some location in memory where the corresponding object resides.

When we assign point to some other variable, or identifier, or pass it as an argument to a function, or return it from a function, we are merely working around with this reference. Any changes made to the object pointed by this reference would be visible in every place where the object is used.

In the case above, when we modify point2's property x in line 4, we are merely modifying the property x of the object in memory referenced by both point and point2. Hence, subsequently accessing x on either object would return the new value.

Shown below is a helpful illustration for this:

An illustration for what's happening internally in the code above.

Below each respective statement (marked by its line number) follows the state of the program after the execution of that respective statement.

The 0xff16 value is a dummy address for the location where the object { x: 0, y: 0} resides in memory. The ... in the memory block represents the fact that there are other things in the memory in addition to the object shown.

In the last section of this illustration, see how point2.x = 10 is executed by changing the value of the x property of the object to 10, yet both point and point2 still refer to the same object.

In short, whenever working with any kind of object in JavaScript (in this case with native objects), remember that it is passed around as a reference, and not as the actual value.

Thereby, if we don't want to mess up with the original object when passing it, it's necessary to first make a copy of the object and then pass that copy.

But how do we make a copy of an object?

Well, this we shall see in the next section below.

Now, one thing to note is that reassigning a value to an identifier that holds a reference to an object won't change the object.

The value stored in the identifier, which a reference to an object, would simply be replaced by the new value — the object itself wouldn't be replaced from memory. All other references pointing to the object would continue to point to it.

Consider the code below:

var point = { x: 0, y: 0 };
var point2 = point;

point2 = { x: 10, y: 10 }; // reassign to point2

console.log(point.x);
console.log(point2.x);
0
10

In line 4, we are reassigning a value to point2 which means that the reference previously stored in it from line 2 is now replaced with another reference, which points to a new object { x: 10, y: 10 } in memory.

Regardless, point still refers to the same object it did at the start of the code — it isn't (and obviously shouldn't have) changed following from the assignment to point2.

Shown below is an illustration for this code:

What happens internally when one of two variables, holding the same reference, is assigned another value.

Iterating over an object

We could use the for...in loop to iterate over all the properties of an object and execute a piece of code for each of them.

The syntax of for...in is quite intuitive:

for ([var ]propName in object) {
   // code to execute for each property
}

propName is a variable that will be assigned the name of the current property of object, as a string, with each subsequent iteration.

Note that, as shown by [var ], the declaration statement var is optional. If the variable propName is declared beforehand, we could simply use propName in object instead of var propName in object.

The for...in loop actually goes over all enumerable properties of the given object, and its whole prototype chain. For now, this is not really relevant for us and likewise we'll ignore it.

But enumerability is an important topic and we'll consider in the next chapter JavaScript Property Attributes when we see how to configure the various internal attributes of a property in JavaScript, and once again in the chapter JavaScript Prototypes.

Anyways, let's use this for...in loop to iterate over all the properties of our very own point object:

var point = { x: 0, y: 0 };

for (var p in point) {
   console.log(point[p]);
}
0 0

The header of the loop creates a variable p and initializes it to the name (which is a string) of the first property of the object point, before beginning the iteration.

See how we are using bracket notation to access the property — this is an example of dynamically accessing a property. Using dot notation, i.e. the expression point.p, is pointless because it would otherwise access a property p on point which simply doesn't exist.

Let's now write a bit more involved body for the loop.

Given the point object above, write a for...in loop to log the following text for each property of point:

'propName' => value

propName is the name of the property while value is its corresponding value.

Shown below is the console output your code should produce:

'x' => 0 'y' => 0

If we use normal string concatenation, we'd get the following code:

var point = { x: 0, y: 0 };

for (var p in point) {
   console.log("'" + p + "' => " + point[p]);
}

Similarly, if we use template literals, we'd get the following:

var point = { x: 0, y: 0 };

for (var p in point) {
   console.log(`'${p}' => ${point[p]}`);
}

As you might agree, using template literals is more readable and intuitive than the typical string concatenation.

For simple objects, just as we are creating here, we could use for...in to create a copy of the objects.

The idea is pretty basic — create a new empty object, iterate over the object whose copy ought to be made using for...in, and for each property, add the the property over the newly-created empty object with the same value as in the original object.

Below we create a function copyObject() that accomplishes this very task:

function copyObject(o) {
   var newObject = {};

   for (var p in o) {
      newObject[p] = o[p];
   }

   return newObject;
}

Let's now use this object to create a copy of point and change the x property of this copy:

function copyObject(o) {
   var newObject = {};

   for (var p in o) {
      newObject[p] = o[p];
   }

   return newObject;
}

var point = { x: 0, y: 0 };
var point2 = copyObject(point); // create a copy of point

point2.x = 10;

console.log(point.x);
console.log(point2.x);
0
10

As is clear by the console output, point and point2 are separate objects — changing one (as we change point2 in line 14) doesn't change the other.

Comparing objects

Let's say we want to check whether two given objects are equal to one another in JavaScript.

The question is how to do so?

Well, there is an extremely simple way.

It's the same equality (==) operator we're used to from the previous chapters. But its definition of 'two equal objects' might be completely different from our definition of 'two equal objects'.

For example, consider the code below:

var point1 = { x: 0, y: 0 };
var point2 = { x: 0, y: 0 };

We have two objects point1 and point2, with exactly the same number of properties, with exactly the same keys, with exactly the same corresponding values.

We say that both of these objects are 'equal to one another'.

Now, let's see what does == have to say about these two objects:

point1 == point2
false

What? == thinks that point1 and point2 aren't equal to one another!

If == returns false, we couldn't expect any better from the even stricter equality operator ===:

point1 === point2
false

Yup, we get the same false.

So what is the reason why point1 and point2 aren't considered equal to one another by these equality operators?

Well, it once again comes to the idea of references.

Recall that objects in JavaScript are stored in identifiers in terms of their reference in memory. In the code above, point1 holds a separate reference and so does point2. They don't hold the same reference — both the variables point to different objects.

It's just that visually, both the objects, pointed to by point1 and point2, seem identical to one another — internally they ain't equal.

When two objects are compared via the == operator or, for that matter, by the === operator, it's not the objects that are compared against one another, but rather their references.

This fact deserves more emphasis:

Two objects in JavaScript are compared by their references.

If the references of both the objects are the same, the objects are considered equal.

Note that when comparing two objects with one another, there is no distinction between using the == (equality) operator for the comparison or the === (strict-equality) operator — both work the same way.

With this in mind, can you determine the log of the code below?

var point1 = { x: 0, y: 0 };
var point2 = point1;

console.log(point1 === point2);

Hmm. Let's see...

point1 is assigned to point2 which simply means that point2 holds the same reference as point1. Likewise, point1 == point2 should return true.

Time to see the console:

true

Just as we reasoned, it does.

As we shall see in the following chapters, comparing two objects with one another is an extremely common operation in JavaScript programs.

Anyways, at the start of this section we showed a piece of code with two different objects point1 and point2 that were visually identical to one another.

What if we actually want to check whether two given objects are visually identical to one another i.e they have the same number of key-value pairs, each of which is identical to a key-value pair in the other object?

Well, even as of the time of this writing, when the latest ECMAScript 2021 spec is already released approximately two months ago, there is no native way to do so in JavaScript.

You ask why.

Perhaps, because it's not a very efficient business to do. And even more importantly, because there shouldn't be a need to use such a comparison in most cases.

If you feel that you definitely need such a comparison, then there are multiple way to do so, all boiling to a custom function created to perform the comparison.

In the next exercise, we get you to think how to create such a function and then actually create one.

Checking for a given property

While working with JavaScript, what's even more mainsteam than determining whether two objects are equal to one another is to test the existence of a particular property on a given object and then perform an action based on the result.

There are multiple ways to do this. Obviously, all involve an if conditional. The difference just lies in the expression that tests for the property's existence.

Retrieving the property

Of all the ways, the most basic one is to retrieve the property via a normal property access expression.

If the property access expression yields a truthy value, we assume that the property exists, however if it yields a falsey value, we assume that the property simply doesn't exist.

Consider the code below:

var point = { x: 0, y: 0 };

if (point.z) {
   console.log("We're modeling 3D!");
}
else {
   console.log("It's only 2D.");
}
It's only 2D!

Since z doesn't exist on the object point, point.z evaluates to undefined which gets coerced to false, hence the if conditional fails, moving execution into the else block.

Now, as you might've already guessed, this technique has a couple of pitfalls.

Let's say that the point object has a property z with the value 0, as shown below:

var point = { x: 0, y: 0, z: 0 };

if (point.z) {
   console.log("We're modeling 3D!");
}
else {
   console.log("It's only 2D.");
}

Regardless, the if conditional would still fail, and we'd get the same output as before:

It's only 2D.

This is because point.z evaluates to 0 which then gets coerced to the Boolean false, and as a result the if conditional fails causing exeuction to jump into the else block.

To boil it down, we surely couldn't use this technique to check for a property's existence, at least in the case of our point object.

This technique is useful when we are sure that if the property exists, then it wouldn't have a falsey value (such as 0, '', false, null).

It it used quite extensively in most of the feature detection code on the front-end as we shall see in the HTML DOM unit.

Feature detection is a common routine of JavaScript programs to check whether a given feature exists in the browser running the current program. It came into existence due to browser inconsistencies for numerous features. We shall see all these details in the HTML DOM unit.

Most features, if they exist in JavaScript, are represented by objects and likewise this direct-property-access technique works in most cases (but not all).

In our case, since the point object had its z property with the value 0, which coerces to the Boolean false, it was meaningless to use this technique.

Property's value compared with undefined

The second way to check for a property's existence is merely an extension of the previous way.

Previously, we retrieved the respective property and used the retrieval expression solely inside the if conditional. This, as we saw above, fails when the property exists but has a falsey value such as 0, '', null and so on.

A more effective way is to compare the value of the property-retrieval expression with undefined using the !== operator. If true is returned, we know for sure that the property exists, or else, if false is returned, we assert that it doesn't it.

Simple, isn't this?

Let's employ this idea in our old code snippet from above:

var point = { x: 0, y: 0, z: 0 };

if (point.z !== undefined) {
   console.log("We're modeling 3D!");
}
else {
   console.log("It's only 2D.");
}
We're modeling 3D!

Although this technique works with a great amount of properties that contain falsey values (such as 0, '', null, false), it still falls astray of one case.

Can you figure out which case is that?

Well, if the property is set to the value undefined, its comparison with undefined using the !== operator, as demonstrated above, would be completely useless.

Consider the following code:

var obj = { x: undefined };

if (obj.x !== undefined) {
   console.log("The property x exists.");
}
else {
   console.log("The property x does NOT exist.");
}
The property x does NOT exist.

The property x exists on obj, yet the if conditional fails. The reason is quite apparent — obj.x returns undefined, and hence obj.x !== undefined returns false.

To boil it down, this second technique is not OK to test a property's existence whose value is undefined.

Forunately, there's an even better way to check for a property's existence that works with this code snippet. Let's see that...

Using the in operator

The binary operator in is used to determine the existence of a particular property on a given object.

Its syntax is quite intuitive — it reads just like an English sentence:

propName in obj

The first operand is the name of the property to search for, given as a string, while the second operand is the object on which to conduct the search for the property.

The operator returns true if the property exists on the object (or its prototype chain), or else returns false.

The fact that in searches for the given property over the prototype chain of the object is not relevant for now. We'll review this idea in the chapter JavaScript Prototypes.

Using in doesn't fall astray of any of the pitfalls of the techniques shown above. The operator is merely concerned with the name of the property, not with its value.

Consider the code below:

var obj = { x: undefined };

if ('x' in obj) {
   console.log("The property x exists.");
}
else {
   console.log("The property x does NOT exist.");
}
The property x exists.

The log shown in the console is evident of the fact that in is able to detect the property x on the object obj.

This means that the most reliable method of checking for a property's existence in JavaScript is to use the in operator.

And what's best about using in is that it's part of ECMAScript since the very first edition of the spec (published in 1997). Hence, it has a great amount of support across all modern and old browsers.

In other words, we have a fully-supported cool feature.

Isn't this super cool?