JavaScript Objects in Depth

You have already learned about JavaScript object in the JavaScript Basics section. Here, you will learn about object in detail.

As you know, object in JavaScript can be created using object literal, object constructor or constructor function. Object includes properties. Each property can either be assigned a literal value or a function.

Consider the following example of objects created using object literal and constructor function.

Example: JavaScript Object
// object literal 
var person = {
  firstName:'Steve',
  lastName:'Jobs'
};

// Constructor function
function Student(){
  this.name = "John";
  this.gender = "Male";
  this.sayHi = function(){
    alert('Hi');
  }
}
var student1 = new Student();
console.log(student1.name);
console.log(student1.gender);
student1.sayHi();

In the above example, person object is created using object literal that includes firstName and lastName properties and student1 object is created using constructor function Student that includes name, gender and sayHi properties where function is assigned to sayHi property.

Note:
Any javascript function using which object is created is called constructor function.

Use Object.keys() method to retrieve all the properties name for the specified object as a string array.

Example: Edit Property Descriptor
function Student(){
  this.title = "Mr.";
  this.name = "Steve";
  this.gender = "Male";
  this.sayHi = function(){    
    alert('Hi');
  }
}
var student1 = new Student();

Object.keys(student1);
Output:
["title", "name", "gender", "sayHi"]

Use for-in loop to retrieve all the properties of an object as shown below.

Example: Enumerable Properties
function Student(){
  this.title = "Mr.";
  this.name = "Steve";
  this.gender = "Male";
  this.sayHi = function(){    
    alert('Hi');
  }
}
var student1 = new Student();

//enumerate properties of student1
for(var prop in student1){
  console.log(prop);
}
Output:
title name gender sayHi

Property Descriptor

In JavaScript, each property of an object has property descriptor which describes the nature of a property. Property descriptor for a particular object's property can be retrieved using Object.getOwnPropertyDescriptor() method.

Syntax:
Object.getOwnPropertyDescriptor(object, 'property name')

The getOwnPropertyDescriptor method returns a property descriptor for a property that directly defined in the specified object but not inherited from object's prototytpe.

The following example display property descriptor to the console.

Example: Property Descriptor
var person = {
  firstName:'Steve',
  lastName:'Jobs'
};

function Student(){
  this.name = "John";
  this.gender = "Male";
  this.sayHi = function(){
    alert('Hi');
  }
}

var student1 = new Student();

console.log(Object.getOwnPropertyDescriptor(person,'firstName'));
console.log(Object.getOwnPropertyDescriptor(student1,'name'));
console.log(Object.getOwnPropertyDescriptor(student1,'sayHi'));

Output:
Object {value: "Steve", writable: true, enumerable: true, configurable: true}
Object {value: "John", writable: true, enumerable: true, configurable: true}
Object {value: function, writable: true, enumerable: true, configurable: true}

As you can see in the above output, the property descriptor includes the following 4 important attributes.

Attribute Description
value Contains an actual value of a property.
writable Indicates that whether a property is writable or read-only. If true than value can be changed and if false then value cannot be changed and will throw an exception in strict mode
enumerable Indicates whether a property would show up during the enumeration using for-in loop or Object.keys() method.
configurable Indicates whether a property descriptor for the specified property can be changed or not. If true then any of this 4 attribute of a property can be changed using Object.defineProperty() method.

Object.defineProperty()

The Object.defineProperty() method defines a new property on the specified object or modifies an existing property or property descriptor.

Syntax:
Object.defineProperty(object, 'property name', descriptor)

The following example demonstrates modifying property descriptor.

Example: Edit Property Descriptor
'use strict'

function Student(){
  this.name = "Steve";
  this.gender = "Male";

}

var student1 = new Student();

Object.defineProperty(student1,'name', { writable:false} );

try
{
    student1.name = "James";
    console.log(student1.name);
}
catch(ex)
{
    console.log(ex.message);
}

The above example, it modifies writable attribute of name property of student1 object using Object.defineProperty(). So, name property can not be changed. If you try to change the value of name property then it would throw an exception in strict mode. In non-strict mode, it won't throw an exception but it also won't change a value of name property either.

The same way, you can change enumerable property descriptor as shown below.

Example: Edit Property Descriptor
function Student(){
  this.name = "Steve";
  this.gender = "Male";
}

var student1 = new Student();

//enumerate properties of student1
for(var prop in student1){
  console.log(prop);
}

//edit enumerable attributes of name property to false
Object.defineProperty(student1,'name',{ enumerable:false });

console.log('After setting enumerable to false:');

for(var prop in student1){
  console.log(prop);
}
Output:
name
gender

After setting enumerable to false:
gender

In the above example, it display all the properties using for-in loop. But, once you change the enumerable attribute to false then it won't display name property using for-in loop. As you can see in the output, after setting enumerable attributes of name property to false, it will not be enumerated using for-in loop or even Object.keys() method.

The Object.defineProperty() method can also be used to modify configurable attribute of a property which restrict changing any property descriptor attributes further.

The following example demonstrates changing configurable attribute.

Example: Edit Property Descriptor
'use strict';

function Student(){
  this.name = "Steve";
  this.gender = "Male";
  
}
var student1 = new Student();

Object.defineProperty(student1,'name',{configurable:false});// set configurable to false

try
{
    Object.defineProperty(student1,'name',{writable:false}); // change writable attribute
}
catch(ex)
{
    console.log(ex.message);
}

In the above example, Object.defineProperty(student1,'name',{configurable:false}); sets configurable attribute to false which make student1 object non configurable after that. Object.defineProperty(student1,'name',{writable:false}); sets writable to false which will throw an exception in strict mode because we already set configurable to false.

Define New Property

The Object.defineProperty() method can also be used to define a new properties with getters and setters on an object as shown below.

Example: Define New Property
function Student(){
  this.title = "Mr.";
  this.name = "Steve";
}

var student1 = new Student();

Object.defineProperty(student1,'fullName',{
  get:function(){
    return this.title + ' ' + this.name;
  },
  set:function(_fullName){
    this.title = _fullName.split(' ')[0];
    this.name = _fullName.split(' ')[1];
  }
});

student1.fullName = "Mr. John";

console.log(student1.title);
console.log(student1.name);
Output:
Mr.
John