Is it possible to make a object property have two names but one connected value?

Is it possible to make a object property have two names but one connected value?

For example, here would be psuedo code what I am asking:

var object = {
"A" || "a": 97,
"B" || "b": 98
}

If I did:

object["a"]

or

object["A"]

It would return 97.

If I were to change the 97 value to 99, it would be the same thing for both letters.

Is this possible? I know switch statements exist, but I am trying to do this to save space. It is fine if it isn’t possible, just curious.

This is a bad reason to try to do what you’re doing: you’re obfuscating to save space. Make things obvious, not clever and non-obvious. Anyway:

If you want to dynamically access an object:

obj {
  A: 97,
  a: 97,
}

Wherever your want to access:

obj["a"| "A"]

Or maybe you use a function:

function getCode (obj, char) {
  return obj[char.toLowerCase()]
}

Then you don’t need to have multiple keys.

obj {
  a: 97,
};

getCode (obj, "A")
getCode (obj, "a")

However, if it’s literally case-insensitive keys, JS allows it, this is how you do that:

const caseInsensitiveKeyHandler = {
  get: function (obj, prop) {
    if (prop.toLowerCase() in obj) {
      return obj[prop.toLowerCase()];
    }
};

Then if it’s like your example

var myObj = new Proxy(obj, caseInsensitiveKeyHandler);

And use myObj instead of obj. Note this is normally a super bad idea: it will work perfectly, and you will get a object that accepts case insensitive keys, but it is reflection, and you make things incredibly non-obvious.

3 Likes

I really have to thank you for this question. It was a fun challenge to learn about, but the answer is, oddly, YEP! Javascript has a fun thing called a Proxy. You can use it to define handlers for object properties. Here are some reasons you might use it:

  • Suppose a property doesn’t exist - I can make it return SOMETHING, rather than an error.
  • Suppose I want to validate before adding a property - I can use a Proxy to check validation.
  • Suppose I want property names to be case-insensitive. Proxy can do that too!

So first, you define the proxy handler, then you wrap your object in it. Here’s the code I used to play with this:

/***
 * This propertyHandler will be a proxy, that operates on *ALL* get or set operations on my object.
 *  Basically, before the property is gotten or set, it converts the property name to lower case.
 ***/
const propertyHandler = {
  get: function(obj, prop){
    const propName = prop.toLowerCase();
    return obj[propName];
  },
  set: function(obj, prop, value){
    const propName = prop.toLowerCase();
    obj[propName] = value;
  }
};

// We wrap a generic object with a Proxy handler, and we pass in our object above.
let myObj = new Proxy({}, propertyHandler);

// and this works - a and A are functionally the same.
myObj.a = "foo";
console.log(myObj.A);

myObj.aReallyLongPropertyNameInMixedCaSe = 42;
console.log(JSON.stringify(myObj) );

(see it in action here: https://repl.it/@TobiasParent/proxiesInJSObjects)

However, as @DanCouper (who beat me to the punch AGAIN) has said, it’s a terrible idea to do this. It may make it easier to avoid having to remember whether a property name is upper or lower or mix case, but it also makes it very easy to accidentally overwrite properties, and it’s encouraging lazy coding.

Fun to know, not something I’d encourage in actual practice.

2 Likes

@snowmonkey @DanCouper

I wish I could give both of you the solution. Both of your answers were helpful and informative.

Because this is a bad practice, I will just stick to the more simple making a property for every condition type thing.

Thanks!

1 Like

Why do you need a property for each one? What is the usecase here, because there is probably a better solution than manually writing out each property, which seems to be likely to be error-prone

edit: this seems like it contradicts what I said at first, but it’s a different reasoning: just writing out all the properties is likely to make it easy to introduce errors (conversely, using reflection tends to mean you’re deliberately altering how you would expect JS to normally work, which again makes it very easy to make errors)

1 Like

Again, this did lead to an interesting exploration of Proxy in javascript. I hadn’t really tinkered much with it, but I can see that being something MASSIVELY useful. Pre-validation for objects you’ll be sending to the server (for example, if you’re storing your JSON to something like FireBase, where there may not be robust object validation), which could be useful in a data store.

While this might not be the best use of that function, I think it is a valid experiment, and a solid question you led with. Keep up the great work! :wink:

Yeah, they’re super powerful. There’s a big performance hit though, but that often isn’t too much of an issue. It’s metaprogramming though, so it can get super confusing, esp given Proxies and Reflection can alter, at runtime, how the language normally works. immer is a really good example of it being used well I think – it’s an immutability library, and it’s ridiculous how much simpler it is than Immutable or similar, that’s all due to it using Proxies.

1 Like