Locking Down Object Properties in JavaScript

JavaScript gives us powerful tools to control exactly how object properties behave. One of the most useful is Object.defineProperty(), which lets us create properties that can’t be accidentally changed.

Why Prevent Property Changes?

Imagine building a configuration object for an app:

const appConfig = {
  apiKey: '123-abc',
  maxConnections: 5,
  debugMode: false
};

What if someone accidentally changes these values?

// Oops! This changes our API key
appConfig.apiKey = 'invalid-key';

Creating Read-Only Properties

Here’s how we can protect important values:

const appConfig = {};

Object.defineProperty(appConfig, 'apiKey', {
  value: '123-abc',
  writable: false // Makes the property read-only
});

Now attempts to change it will fail:

appConfig.apiKey = 'new-key'; // Fails silently

console.log(appConfig.apiKey); // Still '123-abc'

Strict Mode Makes It Better

In strict mode, attempts to change read-only properties throw errors:

'use strict';

appConfig.apiKey = 'new-key'; 
// TypeError: Cannot assign to read only property

Important Options

Object.defineProperty accepts several configuration options:

Object.defineProperty(obj, 'property', {
  value: 'some value',    // The property's value
  writable: false,        // Can the value be changed?
  enumerable: true,       // Will it show up in for..in loops?
  configurable: false     // Can these settings be changed later?
});

A Real-World Example

Creating a user object with protected properties:

function createUser(id, name) {
  const user = {};
  
  Object.defineProperties(user, {
    id: {
      value: id,
      writable: false
    },
    name: {
      value: name,
      writable: true
    },
    createdAt: {
      value: new Date(),
      writable: false
    }
  });
  
  return user;
}

const newUser = createUser(101, 'Alice');
newUser.id = 999; // Won't work - id is protected

Limitations to Know

While writable: false prevents reassignment, it doesn’t make objects immutable:

const config = {};
Object.defineProperty(config, 'allowedUsers', {
  value: ['admin', 'editor'],
  writable: false
});

// This still works!
config.allowedUsers.push('guest');

When to Use This Pattern

  • Configuration objects
  • Library constants
  • Important metadata that shouldn’t change
  • Creating more predictable APIs

Browser Support

Works in all modern browsers (IE9+). For older browsers, you’ll need alternative approaches.

Conclusion

JavaScript’s Object.defineProperty() gives you fine-grained control over how object properties behave. By marking properties as non-writable, you can protect sensitive values from accidental changes, improving the reliability of your code. This technique is especially useful when building configuration objects, constants, or APIs where stability and predictability matter.

Just remember that while you can stop reassignment, you’re not making objects fully immutable—especially when dealing with arrays or objects as property values. If you need deeper protection, consider combining defineProperty() with other techniques like Object.freeze().

Used wisely, Object.defineProperty() helps you write safer, more intentional JavaScript.

Post a Comment

Your email address will not be published. Required fields are marked *