VOOZH about

URL: https://dzone.com/articles/indexers-in-javascript

⇱ Indexers in JavaScript


Related

  1. DZone
  2. Coding
  3. JavaScript
  4. Indexers in JavaScript

Indexers in JavaScript

Indexers are properties that allow you to index instances of a class like arrays by using the [] notation. In this article, learn how to use them in JavaScript.

By Nov. 21, 21 · Code Snippet
Likes
Comment
Save
11.3K Views

Join the DZone community and get the full member experience.

Join For Free

Some modern object-oriented languages have the concept of indexers, which are properties that allow you to index instances of a class just like arrays by using the [] notation. In this article, I would like to show you how to do it in modern JavaScript.

Here’s an example in C#:

C#
class Statuses {
 private Dictionary<string, Status> inner = new Dictionary<string, Status>(); 
 // implement the indexer 
 public Status this[string name] { 
 get => inner[name]; 
 set => inner[name] = value; 
 } 
}

class Program { 
 static void Main(string[] args) { 
 Statuses s = new Statuses(); 
 // refer to the property by using the [] notation 
 s["paid"] = Status.Paid; 
 s["pending"] = Status.Pending; 
 } 
}

Unfortunately, this is not yet possible in modern ES6. However, ES6 has certain mechanisms that allow you to achieve this kind of behavior, although this may look less elegant than in C#.

ES6 has a special proxy class that allows you to intercept calls to the base class. Thus, it becomes possible to handle calls to class fields in a special way.

Let’s repeat our C# example in JS without any tricks.

JavaScript
class Statuses {
 #statuses = new Map();
 
 getStatus(key) {
 // there may be complex logic here
 return this.#statuses.get(key);
 }

 setStatus(key, value) {
 //there may be complex logic here
 this.#statuses.set(key, value);
 }

 hasStatus(key) {
 return this.#statuses.has(key);
 }
}

const statuses = new Statuses();
statuses.setStatus('paid', ...);
statuses.setStatus('pending', ...);
statuses.hasStatus('paid'); => true

To add a status to the set, we use setStatus() instead of the [] notation. Let’s fix this by adding some proxy magic. To do this, let’s declare a constructor in the Statuses class and return its proxy wrapper with get and set accessors instead of the Statuses instance.

JavaScript
constructor() {
 return new Proxy(this, {
 // overrides getting Statuses.name
 get(target, name) {
 if (name in target) {
 const result = target[name];
 return typeof result === 'function' ? result.bind(target) : result;
 }
 return target.getStatus(name);
 },
 // overrides getting Statuses.name
 set(target, name, value) {
 if (name in target)
 target[name] = value;
 else
 target.setStatus(name, value);
 return true;
 }
 });
}

Here we need to clarify some code for the get accessor:

JavaScript
if (name in target) {…}

This fragment is needed to access the class properties and methods (for example, hasStatus), and only if the class has no such property or method, the call will go to getStatus().

JavaScript
return typeof result === 'function' ? result.bind(target) : result;

Here, functions are bound to target (i.e. to the Status instance). Otherwise, they will receive this = Proxy inside.

After creating such a constructor, the required syntax becomes available to us:

JavaScript
const statuses = new Statuses();

statuses['paid'] = …;
statuses['pending'] = …;

statuses.has('paid'); // true
console.log(statuses['pending']);

Although we have achieved the desired result, the JS code looks more like a crutch and I would recommend using it only if you port the existing code from another language (C#, Delphi) where such properties were actively used.

In turn, I’d be interested to know if there are any other ways to implement the [] notation for invoking a getter/setter without using a proxy.

JavaScript

Opinions expressed by DZone contributors are their own.

Related

  • When Angular APIs Return 200 but the Frontend Is Already Failing Users
  • 5 Layers of Prompt Injection Defense You Can Wire Into Any Node.js App
  • Boosting React.js Development Productivity With Google Code Assist
  • Why Angular Performance Problems Are Often Backend Problems

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

Let's be friends: