DEV Community

Cover image for JavaScript Objects Recap
Tanmay Agrawal
Tanmay Agrawal

Posted on

JavaScript Objects Recap

Before understanding objects let us now discuss about the primitive and non primitive values:

The primitive values are those which are immutable.
primitive value is a value that has no properties or methods.

3.14 is a primitive value
what does this means?
if x = 3.14, you can change the value of x, but you cannot change the value of 3.14.

primitive data type is data that has a primitive value.

JavaScript defines 7 types of primitive data types:

  • string
  • number
  • boolean
  • null
  • undefined
  • symbol
  • bigint

example:

let str = 'Hello';
str += ' World'; // Create a new string, 'Hello World', and assign it to str

Enter fullscreen mode Exit fullscreen mode

What are JS Objects then?

A JavaScript object is a collection of named values
Actually they are also variables, but it can hold many pairs of keys and values:

The objects are mutable, means once assigned the values can be changed.

let us set and example of how to declare an object

let person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};
Enter fullscreen mode Exit fullscreen mode

and these are some of the ways in which we can access the properties of the objects

let person = {firstName:"John", lastName:"Doe", age:50, eyeColor:"blue"};

console.log(person.age) //30
console.log(person["firstName"]) //John
Enter fullscreen mode Exit fullscreen mode

This mutability is one of the key characteristics of objects in JavaScript. Let's explore how objects are mutable and what that means in practice:

Changing Object Properties:

You can modify the properties of an object by assigning new values to them. This includes adding new properties, updating existing ones, or deleting properties.

// Creating an object
const person = {
  firstName: 'John',
  lastName: 'Doe'
};

// Modifying properties
person.firstName = 'Jane'; // Update existing property
person.age = 30; // Add a new property
delete person.lastName; // Delete a property
Enter fullscreen mode Exit fullscreen mode

Reference-Based Behavior:

Objects in JavaScript are reference-based data structures. When you assign an object to a variable or pass it as an argument to a function, you are actually working with a reference to the object, not a copy of it. This means that if you modify the object through one reference, those changes will be visible through all references to that object.

const obj1 = { prop: 'value' };
const obj2 = obj1; // Both obj1 and obj2 reference the same object

obj2.prop = 'new value'; // Modifying the object through obj2
console.log(obj1.prop); // Outputs 'new value' because obj1 and obj2 reference the same object
Enter fullscreen mode Exit fullscreen mode

Passing by Reference:

When you pass an object as an argument to a function, you are passing a reference to that object. Any changes made to the object inside the function will affect the original object.

function updateObject(obj) {
  obj.prop = 'updated value';
}

const myObject = { prop: 'original value' };
updateObject(myObject);
console.log(myObject.prop); // Outputs 'updated value' because the object was modified inside the function
Enter fullscreen mode Exit fullscreen mode

Let us consider another example

const person = {
  fname : 'John',
  lname : 'Doe',
  age:30,
  fullName : function(){
    console.log(this.fname + ' ' + this.lname)
  },
  address : {
  street : '123 street',
  city : 'New York',
  state : 'NY'
  }
}

const human = {...person} // the spread operator creates the shallow copy, what does this means ?
human.address.city = 'Los Angeles'
human.age = 31
console.log(person.address.city) //Los Angeles
console.log(person.age) // 30
//so here we can see that the nested object has the same reference to its original one, so
//as the value changes in the copied object it is reflected in the original one as well.

//Also if we assign this person object to another variable, the complete object is copied
//with the reference value

const man = person
console.log(man.fname) //john
man.age = 32
console.log(person.age) // 32 ---notice here it is changed
console.log(human.age) // 31 ---but her id doesnt changed! isnt this is intresting?
Enter fullscreen mode Exit fullscreen mode

If you need a deep copy (i.e., a copy where nested objects and arrays are also cloned), you would need to use a recursive function or a library like lodash to perform a deep copy manually. The spread operator is convenient for shallow copies and quickly creating new objects or arrays with similar structures, but it doesn't handle deep copies.

You can also check the prototype property as follows, more on Prototypes

console.log(Object.getPrototypeOf(person))
Enter fullscreen mode Exit fullscreen mode

Deep copy using the lodash library

This is a simplest way to create the deep copy of the nested objects :

const _ = require('lodash');

const originalObj = {
  a: 1,
  b: {
    c: 2,
    d: [3, 4],
  },
};

const deepCopiedObj = _.cloneDeep(originalObj);

// Modify the copied object without affecting the original:
deepCopiedObj.b.c = 5;

console.log(originalObj.b.c); // Outputs 2 (original is unaffected)
console.log(deepCopiedObj.b.c); // Outputs 5 (modified in the copy)

Enter fullscreen mode Exit fullscreen mode

Defining methods inside objects

In JavaScript, there are several ways to define functions as methods within an object. Methods are functions that are attached to objects and can be called in the context of those objects. Here are some common ways to define functions as object methods:

Method Using Function Expression:

const myObject = {
  myMethod: function () {
    // Method logic
  }
};

Enter fullscreen mode Exit fullscreen mode

Method Using Method Shorthand (ES6):

const myObject = {
  myMethod() {
    // Method logic
  }
};

Enter fullscreen mode Exit fullscreen mode

Method as Arrow Function (ES6):

const myObject = {
  myMethod: () => {
    // Method logic
  }
};

Enter fullscreen mode Exit fullscreen mode

Be aware that arrow functions do not have their own this context; they capture the this value from the surrounding lexical context. See, This Keyword

Method Assignment:

const myObject = {
  myMethod: someFunction
};

function someFunction() {
  // Method logic
}
Enter fullscreen mode Exit fullscreen mode

Computed Property Method Names (ES6):

const methodName = 'myMethod';
const myObject = {
  [methodName]() {
    // Method logic
  }
};
Enter fullscreen mode Exit fullscreen mode

What is Object.assign ?

Object.assign() is a method in JavaScript that is used to copy the values of all enumerable own properties from one or more source objects to a target object. It is often employed for object cloning or to merge objects. It does not create a new object but instead modifies an existing one.

Here's an example of how Object.assign() works:

const target = { a: 1, b: 2 };
const source = { b: 4, c: 5 };

const result = Object.assign(target, source);
console.log(target); // { a: 1, b: 4, c: 5 }
console.log(result); // { a: 1, b: 4, c: 5 }
Enter fullscreen mode Exit fullscreen mode

In this example, the Object.assign() method merges the properties of the source object into the target object. If the target object already has a property that is also present in the source object, the value from the source object overwrites the value in the target object.

The main difference between using Object.assign() and the usual object declaration is that Object.assign() allows you to merge multiple source objects into a single target object, thereby combining their properties. The usual object declaration, on the other hand, simply creates a new object with the specified properties.

For instance, in the case of the usual object declaration:

const obj = { a: 1, b: 2 };
Enter fullscreen mode Exit fullscreen mode

the obj object is created with the specified properties a and b. However, you cannot directly merge properties from another object into it without manually copying each property. Object.assign() simplifies this process by allowing you to merge properties from multiple source objects into a target object in a single step.

Creating Objects with constructor v/s usual Object creation

In JavaScript, you can create objects using either the object constructor syntax or the normal object creation syntax. While both methods achieve the same result of creating objects, they differ in terms of syntax and behavior.

1.Object Constructor Syntax:

   const obj = new Object();
   obj.property = "value";
Enter fullscreen mode Exit fullscreen mode

2.Normal Object Creation:

   const obj = { property: "value" };
Enter fullscreen mode Exit fullscreen mode

The key differences between using the object constructor syntax and normal object creation are as follows:

  • Syntax Clarity and Conciseness: The normal object creation syntax is more concise and easier to read, write, and understand. It allows you to create objects in a straightforward and simple manner.
  • Performance: Normal object creation is generally more performant than using the object constructor syntax, especially when creating multiple objects, as it does not involve the overhead of calling the constructor function.
  • Prototype Chain: When using the object constructor syntax, the created object inherits properties and methods from the Object prototype, while with normal object creation, the prototype chain is not involved.
  • Extensibility: Both approaches allow you to add properties and methods to the object dynamically. However, the normal object creation syntax is more commonly used in modern JavaScript development for its simplicity and readability.

In practice, the normal object creation syntax is widely preferred due to its simplicity, conciseness, and performance benefits. It has become the standard way to create objects in modern JavaScript applications.

Top comments (0)