Using Decorators in JavaScript to Transform Class Variables into Getter and Setter Functions

Looking for suggestions on how to utilize a decorator to transform a class field into a getter/setter. For instance:

class Foo:
    @accessor bar = 0;

const foo = new Foo;

Desiring specific behavior when foo.bar = 1; is executed.

I've experimented with the following approach:

function accessor(target, name, descriptor) {
    let val;
    
    return {
        set: function(newVal) {
            val = newVal;
            console.log("setter called");
        },
        get: function() { return val; }
    };
}

However, this method results in losing the initial value of bar = 0.

Answer №1

To meet the requirements of the class, it is necessary to maintain a private property for storing values.

Currently, decorators proposal and newer Babel plugin do not support class fields, so the older transform-decorators-legacy Babel plugin must be used instead.

According to the transform-decorators-legacy documentation, in order to provide get/set accessors for a property, the initializer method and writable property should be removed from the descriptor object. The initial value from the initializer function needs to be retrieved and assigned to the private property:

function accessor(classPrototype, prop, descriptor) {
  if (descriptor.initializer)
    classPrototype['_' + prop] = descriptor.initializer();

  delete descriptor.writable;
  delete descriptor.initializer;

  descriptor.get = function () { return this['_' + prop] };
  descriptor.set = function (val) { this['_' + prop] = val };
}

class Foo {
  @accessor bar = 0;
}

const foo = new Foo ;
foo.bar = 1;

The initial value (0) will be assigned to the class prototype and will not trigger the set accessor, while subsequent values (1) will be assigned to the class instance and will trigger the set accessor.

It's important to note that this approach may not work with other decorator implementations like TypeScript and decorator proposal due to the non-spec-compliant nature of transform-decorators-legacy.

An ES6 equivalent code snippet that is spec-compliant can be written as follows:

class Foo {
  get bar() { return this._bar };
  set bar(val) { this._bar = val };
}

Foo.prototype._bar = 0;

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The content of the served HTML Table remains static and requires a server restart for any updates to

Having been encountering this issue for quite some time, I have searched extensively for a solution but to no avail. Therefore, I am taking matters into my own hands and posing the question myself. The dilemma is as follows: https://i.stack.imgur.com/UZrQ ...

Is there a way to initiate the focusout event on all input fields within a form simultaneously?

I need a way to trigger focusout every time a user moves to the next field in a form. I don't want to use a class element because it will apply to all fields with that class. Here is an example of what I want to avoid: $("#element1").focusou ...

What steps should I take to update the image src within my slider?

I have a slider image that I want to fade to the next image when a button is clicked. I used JQuery to create a smooth transition when changing the image source, but the image remains the same after fading. Html <button onclick = "prev()" id = "pr ...

How can a PHP script send responseText to AJAX from POST request? I am looking to send a message back with Ajax

I am currently working on setting up a system where Ajax calls upload.php and expects a success or failure message in return. I attempted to use echo "success" in the php script, anticipating that xhr.responseText would capture the message. However, when I ...

Combine the power of JavaScript with Node.js

I am brand new to the world of node and feeling a bit lost when it comes to finding the right solution for my current issue. I would greatly appreciate any guidance towards the best approach. Currently, I am using the Buddy framework to compile coffeescri ...

Phonegap experiencing issues with executing JavaScript code

My attempt to utilize phonegap is encountering an issue where my javascript is not running. Here's what I've tried so far: <html> <head> <meta charset="utf-8" /> <meta name="format-detection" content="telephone=no" / ...

Install Chakra UI in the latest Next.js project directory

Recently, I decided to incorporate Chakra UI v2.4.9 into my Next.js project running on version v13.1.6. To ensure a seamless integration, I followed the detailed instructions provided in Chakra UI's official guide for Next.js. However, I encountered s ...

Redirecting to an Unverified Website

I encountered an issue in my service.ts file where VeraCode code scan is failing Flaws by CWE ID: URL Redirection to Untrusted Site ('Open Redirect') (CWE ID 601)(16 flaws) Description The web application is vulnerable to URL redirection attacks ...

The attempt to execute 'removeChild' on 'Node' was unsuccessful due to an uncaught DOMException

'removeChild' execution failed on 'Node': The specified node is not a child of this element. Whenever I run the code below, an error occurs. Is there a solution to fix this issue? function clickLinks(links) { for(var item in links) ...

Is there a way to retrieve a comprehensive list of all the potential routes in my nuxt.js project?

Is there a way to retrieve a list of all the potential routes in my nuxt.js project? (this would include all URLs) ...

Implementing Ideone API functionality on Codeigniter with the use of ajax, javascript, and soapclient

I am new to using Codeigniter and I apologize if my question is basic. I found some code on this site: Working with IDE One API (Full project code available here) and I'm attempting to incorporate it into Codeigniter. I have been able to get it worki ...

The JavaScript event "onmousemove()" functions correctly in Chrome, however, it does not work as expected in Firefox

I tried searching on various platforms, but unfortunately, I couldn't find a solution to my issue. At the bottom of the page, there are four towers that are supposed to display different images with less transparency when hovered over. This functiona ...

The TypeScript optional callback parameter is not compatible with the anonymous function being passed to it

Encountering an issue with TS callbacks and function signatures. Here is my scenario: ... //inside a class //function should accept a callback function as parameter refreshConnection(callback?: Function) { //do something //then ca ...

Using dates as the X axis in Chart.js can be achieved even when there is no corresponding Y axis value

My goal is to ensure that the chart always displays a value on the final X axis, I am unable to use "distribution: 'series'" as it causes the chart to go out of scale, Guessing the correct value to set for "time: {min / max}" in order to exceed ...

Angular factory variable scoping

I am encountering an issue with altering the folders variable (an array) within the return statement of my Angular factory. It seems to work for the create action, but I am having trouble with the scope of the variable in the factory. This code works: fo ...

Creating an autocomplete/autosuggestion feature using AJAX and displaying the results in a table separate from the form

I am in the process of creating a basic webpage with a search engine. I have learned that to incorporate autocomplete/autosuggest with a form, using ajax is necessary. This is acceptable to me. There are numerous solutions available online, but unfortunate ...

Using app.use in Express/node.js for routing causes the client to experience excessive delays

After setting up the server-side code in app.js, I encountered an issue: console.log("Server started. If you're reading this then your computer is still alive."); //Unnecessary test command to make sure everything works. var express = require("expre ...

Updating the dimensions of a Shape in ThreeJS

Is it possible to update the dimensions of a Shape in ThreeJS without the need to recreate the entire shape each time? I am creating a square based on the user's mouse movement to define the area of zoom. Currently, I recreate the square shape and ad ...

What is the best way to flatten object literal properties?

I have received an object from a legacy server that I need to restructure on the client-side using JavaScript, jQuery, or Underscore.js. Here is the original structure of the object: [ { "Id":{ "LValue":1, "Value":1 }, ...

Intercepting HTTP requests on specific routes with Angular 4+ using an HTTP Interceptor

I've developed an HTTP_INTERCEPTOR that needs to function on certain routes while excluding others. Initially, it was included in the main app module file. However, after removing it from there and adding it to specific modules, the interceptor conti ...