Objects

Conceptually, Objects are the same in all programming languages i.e they represent real-world things that we want to represent inside our programs with characteristics/properties and methods.

For example, if your object is a student, it will have properties like name, age, address, id, etc and methods like updateAddress , updateName etc.

In JavaScript think of an object as a list that contains items, and each item (a property or a method) in the list is stored by a key-value pair in memory as reference.

Let’s see an object example.

const firstObj = {

1: "deepak",

"age": 28

}

firstObj is an object with 2 properties 1 and age and value as deepak and 28 .

JavaScript objects are somewhat different in the way they are created. There is no requirement for a class as such and can be declared using literal notation.

Object Creation

We can create objects in many ways in javascript, let’s look at each one of them.

Object literal (D\direct way). Object literals are a comma-separated list of key-value pairs wrapped in curly braces. Object literal property values can be of any data type, including array literals, functions, nested object literals or primitive data type.

var student = {

id: 1,

name: "deepak",

age: "27",

updateAddress: () => {

// logic to update address

},

grade: ['A', 'A+', 'A']

}

Note: The student object keys in the above can be accessed via Dot notation i.e student.id , student.name or via a square bracket notation i.e student[‘id’] , student[‘name’] , etc

2. Object.create() . the method creates a new object with the specified prototype and properties of the old object.

Note: Every JavaScript function has a prototype object property by default(it is empty by default). Methods or properties may be attached to this property.

// syntax - Object.create(prototype[, propertiesObject])

var newStudent = Object.create(student);

// this create a new object with old object added in its prototype // chain

Below is the output of the object __proto__

Object in Javascript

We can now add new properties and data to newStudent object using the method we are learning here.

Note: The newStudent will have access to the parent student object keys and value as it's been added to newStudent prototype chain and this is one way we do inheritance in javascript. That is, newStudent will store a link to student object. This parent object is also consulted when a property is read. The parent can have a parent and so on. This is repeated until we reach an object that does not have any parent i.e the parent is null .

3. Object Instance . The use of Object constructor in conjunction with the “ new ” keyword allows us to initialize new objects.

Let’s take a look by an example

const newObj = new Object();

newObj.name = ‘Deepak’;

newObj.location = ‘Delhi, India’;

However, the above method using new Object() is not well suited to programs that require the creation of multiple objects of the same kind, as it would involve repeatedly writing the above lines of code for each such object.

To deal with this problem, we can use the next method

4. Object construtor . Constructors can be useful when we need a way to create an object “type” that can be used multiple times without having to redefine the object every time and this could be achieved using the Object Constructor function.

Let’s take a look by an example

function Vehicle(name, model) {

this.name = name;

this.model = model;

}



let car1 = new Vehicle('Fiesta', '2019');

let car2 = new Vehicle('DC avanti', '2018');

We created two objects with the same property but with different values.

5. Object.assign() . this is another method to create a new object from other objects.

Note: We will cover enumerable/ownership in the next part, so bear this with me.

It copies the values of all enumerable own properties from one or more source objects to a target object. It will return the target object. Let’s understand by an example:

var obj = { a: 1 };

var copy = Object.assign({}, obj);

console.log(copy); // { a: 1 }

There are a lot of use case for Object.assign() like Object cloning, Merging objects, etc.

6. Object.fromEntries() . Method transforms a list of key-value pairs into an object. Let’s take a look by an example

const entries = new Map([

['foo', 'bar'],

['baz', 42]

]); const obj = Object.fromEntries(entries); console.log(obj);

// expected output: Object { foo: "bar", baz: 42 }

Note: The best way to create objects is via Literal notation as it takes less space in the source code. It’s clearly recognizable as to what is happening, so using new Object() , you are really just typing more and (in theory, if not optimized out by the JavaScript engine) doing an unnecessary function call. Also, literal notation creates the object and assigns the property in same line of code which is not the case with others.

How to add/update and remove property of an object

Properties to an object can be added via dot or bracket notation as discussed earlier. Let’s look by an example

const a = {};

a.name = 'deepak';

a['city'] = 'delhi';

a[1] = 'dope';

Here, name and city are object properties.

An object can only contain a single key with one value. We can’t have a single key having two different values.

Property names can be a string or a number or special character, or dynamic properties, but if the property name is not a string, it has to be accessed with the bracket notation. So if we need to access property 1 in the above example, we can do a[1] but a.1 will return a syntax error. However, property case i.e a.name or a["name"] will work.

a.first name = 'deepak' // will return syntax error

a['first name'] = 'deepak' // will work

To update a property we can again use both of the above notation types. If we add value to already created properties then the value is updated else created.

a.city = 'new york';

The above will update the city value from delhi to new york .

We can also create and update properties to an object via Object function methods like Object.defineProperties() or Object.defineProperty()

Object.defineProperties(a, {

pincode: {

value: 10012,

writable: true

},

property2: {}

}); console.log(a.pincode); // 10012

To delete a property of an object we can use delete keyword and we can use both notations to do so.

delete a['city'];

delete a.city;

The return value delete is true if the property was successfully deleted. Else, it will be false .

Do you know a way to not to allow properties update or delete? If yes, comment down below if not then don’t worry I will deep dive into next article with such more questions.

How to iterate on object properties?

There will be a situation while coding practically where we want to access all object key-value pairs.

Using Loops — for in and for of loops

In case of for in, it iterates over an object and returns the properties one by one.

for (const key in a) {

console.log(key, a[key]);

}

Key will have all the properties one by one and a[key] will return the value. For in loop also iterate over the prototype chain and will return the parent keys as well, so don’t be surprised if you see more keys. To avoid seeing more key we can do a hasOwnProperty check to get the current object keys only.

In case of for of, it iterates over iterating over iterable objects. For more read here.

There are various methods in the Object function which helps to access object properties and values, not the prototype chain.

Object.keys() or Object.getOwnPropertyNames() . Rreturns an array of string keys.

const keys = Object.keys(a)

// return ["name", "first name", "city", "1"]; const newKeys = Object.getOwnPropertyNames(a);

// return ["name", "first name", "city", "1"]; keys.map(key => console.log(a[key]));

// return ["deepak", "deepak", "new york", "dope"];

2. Object.values() . Returns an array of values.

const keys = Object.values(a); // return ["deepak", "deepak", "new york", "dope"]

3. Object.entries() . Returns an array of [key, value] pairs.

const data = Object.entries(a); // returns

[ ["1", "dope"], ["name", "deepak"], ["first name", "deepak"], ["city", "new york"]]

From what we see above order of appearance of properties is not fixed in an object.

How to check properties existence in an object

There are three ways to check the property exists in an object or not.

Using hasOwnProperty . This method returns a boolean indicating whether the object has the specified property as its own property, not the parent/inheriting property.

console.log(a.hasOwnProperty(1)); // return true;

console.log(a.hasOwnProperty('1')); // return false; const b = Object.create(a); // this will add a as parent of b

console.log(b.hasOwnProperty(1)); // return false

Note: hasOwnProperty returns true even if the value of the property is null or undefined .

What if we have hasOwnProperty as a property name in an object? Comment your thoughts below.

2. Using in operator — The in operator returns true if the specified property is in the specified object or its prototype chain i.e inside in its parent.

console.log(1 in a); // return true;

console.log('1' in a); // return false; const b = Object.create(a); // this will add a as parent of b

console.log(b.hasOwnProperty(1)); // return true

Note: hasOwnProperty only checks for current object property whereas in operator check for current+parent properties

3. Using a custom made function

There are various ways to check if a property exists or not via a custom method. One of them is through Object.keys For eg.

Object.keys(a).indexOf(1) !== -1 // return true

Comment down below your custom method to do the same 😃.

What are copy by reference/sharing and copy by value and how does it applies to object?

The difference is, by the value, we mean that new memory allocation is done each time something is created whereas in case of reference we point to already created memory space.

In the context of javascript, all primitive data types are allocated memory via value method and for an object, it's both copies by value or reference depending upon the implementation.

// pass by value

let a = 5;

let b = a; a = 6;

console.log(b) // return 5 as each time a new memory is allocated // pass by reference

const a = {x: 1};

const b = a; a.x = 3;

console.log(b.x) // it returns 3 as its a shared memory between a and b

What is a shallow and deep copy/cloning of objects?

The core difference between shallow and a deep copy is how the properties are copied to the new object.

In Shallow copy, the new object share the data with the older object i.e in case of the above example using = create a shallow copy b of a object. So pass by reference is a shallow copy in most cases.

Also, A shallow copy will duplicate the top-level properties, but the nested object is shared between the original(source) and the copy(target).

Another way to shallow copy is by the usage of Object.assign() which is discussed in starting. Let’s look at the example

let obj = {

a: 1,

b: {

c: 2,

},

} let newObj = Object.assign({}, obj);

console.log(newObj); // { a: 1, b: { c: 2} }



obj.a = 10;

console.log(obj); // { a: 10, b: { c: 2} }

console.log(newObj); // { a: 1, b: { c: 2} } newObj.b.c = 30;

console.log(obj); // { a: 10, b: { c: 30} }

console.log(newObj); // { a: 20, b: { c: 30} }

As we can see above obj.b.c = 30 that is a pitfall of Object.assign() . Object.assign only makes shallow copies. Both newObj.b and obj.b share the same reference to the object because of individual copies were not made, instead, a reference to the object was copied.

In Deep copy, the new object will have its own set of key-value pairs (having the same value as original ones) rather than sharing.

Let’s see some ways to do a deep copy

JSON.parse(JSON.stringify(object))

let obj = {

a: 1,

b: {

c: 2,

},

}



let newObj = JSON.parse(JSON.stringify(obj));



obj.b.c = 20;

console.log(obj); // { a: 1, b: { c: 20 } }

console.log(newObj); // { a: 1, b: { c: 2 } } (New Object!)

The issue with the above is we cannot copy the user-defined object functions or keys whose values are undefined , or a Symbol .

let obj = {

a: 1,

b: {

c: 2,

},

d: () => {}

}



let newObj = JSON.parse(JSON.stringify(obj));



console.log(newObj); // { a: 1, b: { c: 2 } } (New Object!)

Also, this method doesn’t work for circular objects.

Note: Circular objects are objects that have properties referencing themselves.

let obj = {

a: 'a',

b: {

c: 'c',

d: 'd',

},

}



obj.c = obj.b;

obj.e = obj.a;

obj.b.c = obj.c;

obj.b.d = obj.b;

obj.b.e = obj.b.c;



let newObj = JSON.parse(JSON.stringify(obj));



console.log(newObj);

The above will throw an error saying converting circular structure to JSON.

2. Using the ES6 spread operator —

let obj = {

one: 1,

two: 2,

nested: {

three: 3

},

}



let newObj = { ...obj };

console.log(newObj); // { one:1, two:2, nested: {three: 3}}

(New Object!)

However, nested is still copied shallowly.

How to compare two objects?

The equality == and strict equality === operators for objects work exactly the same i.e two objects are equal only if they share the same reference to the memory.

For instance, if two variables reference the same object, they are equal: