Is it possible for a JavaScript object to both return a value and log to console?

I’m working with an object that maps letters to numbers:

const LETTER_TO_NUMBER = {
  x: 10,
  y: 20,
  z: 300
};

I use it like this:

let letter = 'x';
// some code might change letter
const num = LETTER_TO_NUMBER[letter];

The problem is when letter is ‘z’, it’s an error. I want to log “Number maxed out at 300” when this happens.

Can I do this inside the object? I tried:

const LETTER_TO_NUMBER = {
  x: 10,
  y: 20,
  z: (() => { console.log('Number maxed out at 300'); return 300; })()
};

But it logs right away, not when LETTER_TO_NUMBER[‘z’] is called.

I could check after using the object:

if (num === 300) {
  console.log('Number maxed out at 300');
}

But I’d rather not do this check every time. Is there a better way to handle this in JavaScript?

hey, you could try using Object.defineProperty() to add a custom getter for ‘z’. it’d look somethin like this:

Object.defineProperty(LETTER_TO_NUMBER, ‘z’, {
get() {
console.log(‘Number maxed out at 300’);
return 300;
}
});

this way, it only logs when ‘z’ is accessed. pretty neat solution withot changing ur original object much!

I’ve faced a similar challenge in my projects. One approach that worked well for me is using a Proxy object. It allows you to intercept property access and perform custom actions. Here’s how you could implement it:

const LETTER_TO_NUMBER = new Proxy({
  x: 10,
  y: 20,
  z: 300
}, {
  get: function(target, prop) {
    if (prop === 'z') {
      console.log('Number maxed out at 300');
    }
    return target[prop];
  }
});

This way, you maintain the original object structure, but when ‘z’ is accessed, it logs the message and returns the value. It’s clean, doesn’t require additional checks, and keeps the logging logic encapsulated within the object itself.

Keep in mind that Proxies have a slight performance overhead, but for most applications, it’s negligible. This solution has served me well in similar scenarios, providing both flexibility and cleaner code structure.

An alternative approach you might consider is using getter methods. This allows you to define custom behavior when accessing object properties. Here’s how you could implement it:

const LETTER_TO_NUMBER = {
  x: 10,
  y: 20,
  get z() {
    console.log('Number maxed out at 300');
    return 300;
  }
};

This method keeps your original object structure intact while adding the desired logging functionality. The console.log will only trigger when ‘z’ is accessed, solving your initial problem. It’s a clean solution that doesn’t require external checks or complex proxy setups.

In my experience, this approach offers a good balance between simplicity and functionality, especially for objects with a limited set of properties that need special handling.