How to Clear a Javascript Object


Today we dive deep into the art of clearing objects in JavaScript. This comprehensive guide will cover different property types (inherited, enumerable), various techniques for effectively resetting or clearing JavaScript objects, including simple objects, nested objects, and those with non-enumerable properties, and immutability. We’ll also address common pitfalls, best practices and a nice Practice Question to cement the concepts.


Understanding Types of Object Properties Types in JavaScript

Own, inherited, Enumerable and Non-Enumerable Properties

JavaScript objects have properties that can be categorized as either own properties or inherited properties. Furthermore, these properties can be either enumerable or non-enumerable.

  • Own Properties: These are properties that an object directly contains. They are not inherited from the object’s prototype chain.
  • Inherited Properties: These properties are inherited from an object’s prototype. They are not directly defined on the object itself.
  • Enumerable Properties: These are properties that show up in for...in loops. Simple assignment using dot notation (e.g., obj.property = value) or square bracket notation (e.g., obj['property'] = value) creates enumerable properties.
  • Non-Enumerable Properties: These properties do not show up in for...in loops. They are typically defined using Object.defineProperty() with enumerable: false.

Example of own vs inherited Properties

JavaScript
function User(name) {
  this.name = name; // Own property
}

User.prototype.greet = function() { // Inherited property
  return `Hello, ${this.name}!`;
};

const user1 = new User('Alice');
console.log(user1.hasOwnProperty('name')); // true (own property)
console.log(user1.hasOwnProperty('greet')); // false (inherited property)

Example of Enumerable and Non-Enumerable Properties

JavaScript
const user = { name: 'Bob' }; // Enumerable property
Object.defineProperty(user, 'age', {
  value: 30,
  enumerable: false // Non-enumerable property
});

for (const key in user) {
  console.log(key); // Outputs: name
}

console.log(Object.getOwnPropertyNames(user)); // Outputs: ['name', 'age']

Ways to Clear Javascript Object

Clear a Simple JS Object Using for...in Loop, hasOwnProperty and delete

A straightforward method to clear an object is using a for...in loop along with the delete operator. This method is effective for objects with enumerable properties.

JavaScript
const userSettings = { theme: 'dark', notifications: true };

for (const key in userSettings) {
  if (userSettings.hasOwnProperty(key)) {
    delete userSettings[key];
  }
}

console.log(userSettings); // Outputs: {}
  • Best Practice: Always check if the property belongs to the object itself, not inherited, using hasOwnProperty.
  • Pitfall: This method might not be performance-efficient for large objects due to the delete operator.

Using Object.keys() and forEach() or for…of loops

This method uses Object.keys() to retrieve an array of an object’s own enumerable property names, then iterates over them with forEach(). Alternatively, a for...of loop can be used in combination with Object.keys().

JavaScript
// forEach example:
const sessionData = { token: 'abc123', expires: '2023-01-01' };

Object.keys(sessionData).forEach(key => {
  delete sessionData[key];
});

console.log(sessionData); // Outputs: {}

// - - - - - - - - - - - - - -

// for...of example:
const appConfig = { mode: 'development', debug: true };

for (const key of Object.keys(appConfig)) {
  delete appConfig[key];
}

console.log(appConfig); // Outputs: {}

Clear Nested JS Object,

Sometimes you may need to clear only a nested object within a larger object. The same approach with a for...in loop can be applied. And as a best practice, do check if its the object’s own property.

JavaScript
const userProfile = {
  name: 'Alice',
  details: { age: 30, location: 'Wonderland' }
};

for (const key in userProfile.details) {
  if (userProfile.details.hasOwnProperty(key)) {
    delete userProfile.details[key];
  }
}

console.log(userProfile); // Outputs: { name: 'Alice', details: {} }

Object Reassignment with let

Reassigning an object to an empty object {} is a quick way to clear it. Suitable way :

  • When you don’t have multiple references to the object and it’s declared with let or var. Note that reassigning will not affect other references to the original object. This is important in scenarios where the object is shared or referenced in multiple places.
  • When you need to clear an entire object, especially if it’s large or has many properties, reassigning the variable with let (or var) to an empty object is more efficient. This method is quick and lets the JavaScript engine handle the previous object’s garbage collection.
JavaScript
let settings = { theme: 'light', volume: 70 };
settings = {};

console.log(settings); // Outputs: {}

Using Object.getOwnPropertyNames: Clear Objects with Non-Enumerable Properties

For objects that include non-enumerable properties, Object.getOwnPropertyNames combined with a loop or forEach can be used.

JavaScript
let config = { display: 'bright' };
Object.defineProperty(config, 'volume', {
  value: 'high',
  enumerable: false
});

Object.getOwnPropertyNames(config).forEach(prop => {
  delete config[prop];
});

console.log(config); // Outputs: {}

Tips when Clearing Javascript Objects

  • Multiple References: Reassigning an object with obj = {} creates a new object and assigns it to obj. However, this does not affect other variables that reference the original object. These variables will still point to the original object, which now remains unchanged.
  • Non-Enumerable Properties: Standard loops, like for...in, only iterate over enumerable properties. Non-enumerable properties, which are not listed in Object.keys() or for...in loops, need Object.getOwnPropertyNames or Object.getOwnPropertyDescriptors for their enumeration.
  • Performance Impact of delete: The delete operator can be less performant, especially in browsers and with large objects. It modifies the object’s shape (how properties are stored), leading to potential optimization issues. Reassigning an object to a new empty object is generally more performant as it doesn’t involve property-by-property deletion.
  • Immutable Data Patterns: Utilizing immutable data structures or patterns helps prevent unintended side effects caused by multiple references. In immutable patterns, instead of modifying the original object, operations return a new object, thus avoiding issues with shared references. See detailed explanation below.
  • Prototypal Inheritance and for...in loop: When using the for...in loop, it’s crucial to use hasOwnProperty to check if a property belongs to the object itself and is not inherited from the prototype chain. This prevents inadvertently iterating over inherited properties, which might not be the intended behavior. See detailed explanation below.

Explanation for Immutable Data Pattern

Immutable data patterns involve creating new objects whenever modifications are necessary, rather than changing the existing objects. This approach helps in maintaining the original state and avoiding side effects, especially in scenarios involving shared references.

Consider a scenario where you have a user object and you want to update the user’s address. Instead of directly modifying the original user object, we’ll create a new object with the updated address.

JavaScript
const user = {
  name: 'Alice',
  address: '123 Main St'
};

function updateUserAddress(user, newAddress) {
  return {
    ...user,
    address: newAddress
  };
}

const updatedUser = updateUserAddress(user, '456 Elm St');
console.log(user); // Outputs: { name: 'Alice', address: '123 Main St' }
console.log(updatedUser); // Outputs: { name: 'Alice', address: '456 Elm St' }

In this example, updateUserAddress returns a new object created using the spread syntax (...). This new object contains all the properties of user but with the address property updated. The original user object remains unchanged, demonstrating the principle of immutability.

Explanation for Prototypal Inheritance and for...in Loop

When iterating over an object’s properties using a for...in loop, it’s important to distinguish between the object’s own properties and those it inherits from its prototype.

Let’s illustrate this with an object that inherits from another object through its prototype.

JavaScript
function Person() {
  this.name = 'Alice';
}

Person.prototype.greet = function() {
  return `Hello, ${this.name}`;
};

const person = new Person();

for (const key in person) {
  if (person.hasOwnProperty(key)) {
    console.log(key); // Outputs: name
  }
}

In this example, person has its own property name and inherits the greet method from its prototype. The for...in loop iterates over both properties. However, using hasOwnProperty inside the loop ensures that only the object’s own properties (name in this case) are considered, and the inherited greet method is ignored.

Above approach avoids unexpected behavior when dealing with inherited object properties, ensuring that only the properties belonging directly to the object are processed.


🧪Practice Coding Problem: The Time Capsule

In the spirit of Test Driven Development ( 😁), lets test our understanding by solving a problem.

Imagine you’re building a time capsule in JavaScript. You can add various items to it, but due to a quirky time-space limitation, you can only take items out by completely clearing the capsule and starting over.

Your task is to write two functions for the Time Capsule:

  1. addToCapsule: Adds an item to the time capsule.
  2. clearCapsule: Clears all items from the time capsule.

However, here’s the fun part: The time capsule should be an immutable object!

JavaScript
/**
 * Adds an item to the time capsule.
 *
 * @param {Object} capsule - The current time capsule object.
 * @param {String} item - The item to add to the time capsule.
 * @return {Object} A new time capsule object with the added item.
 */
function addToCapsule(capsule, item) {
  // > > > 👉 Write code here 👈 < < <
}

/**
 * Clears all items from the time capsule.
 *
 * @param {Object} capsule - The time capsule object to clear.
 * @return {Object} A new, empty time capsule object.
 */
function clearCapsule(capsule) {
  // > > > 👉 Write code here 👈 < < <
}

// ▶ Driver Code:
let myCapsule = {};
myCapsule = addToCapsule(myCapsule, 'Dinosaur Toy');
myCapsule = addToCapsule(myCapsule, 'Ancient Coin');
console.log(myCapsule); 
// Outputs: { 'Dinosaur Toy': true, 'Ancient Coin': true }

myCapsule = clearCapsule(myCapsule);
console.log(myCapsule); 
// Outputs: {}
Please attempt before seeing the Answer:
JavaScript
function addToCapsule(capsule, item) {
  return { ...capsule, [item]: true };
}

function clearCapsule(capsule) {
  return {};
}

Explanation:

  • The addToCapsule function creates a new object each time it’s called, adding a new item to the time capsule. It uses the spread syntax to copy properties from the old capsule object and adds the new item.
  • The clearCapsule function simply returns a new, empty object, effectively clearing the time capsule.
  • This approach maintains immutability, as each operation returns a new object rather than modifying the existing one.

Hopefully, this blogpost gives you enough approaches to keep all your javascript objects tidy, and avoid edge cases due to different property types (non-enumerable, inherited props, etc) and even immutability.

Keep clean coding! 🚀👨‍💻🧹

Scroll to Top