Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JavaScript instance level decorators

Is it possible to define a decorator that would be exposed at an instance level in the current iteration of the proposal

For example

function once(target, name, descriptor) {
  let {get} = descriptor;
  var called = false, result;
  if (typeof get === "function") {
    descriptor.get = function() {
      console.log(called);
      if (!called) {
          result = get.apply(this, arguments);
          called = true;
      }
      return result;
   }
  }
  return descriptor;
};

class X {
    @once
    get y() {
      return Math.random();
    }
}

var x1 = new X;
var x2 = new X;


// Should be false
console.log(x1.y !== x2.y)

I'm wanting behaviour similar to doing

class X2 {
  constructor() {
     // Set descriptor manually for this instance
    let descriptor = Object.getOwnPropertyDescriptor(X2.prototype, 'y');
    let d = Object.assign({}, descriptor);
    once(X, "y", d);
    Object.defineProperty(this, 'y', d);
  }
  get y() {
    return Math.random();
  }
}

Babel REPL example

like image 269
megawac Avatar asked Apr 17 '15 16:04

megawac


People also ask

Can you use decorators in JavaScript?

Since the decorator pattern involves wrapping a piece of code with another without modifying the wrapped code, decorators have been in use in JavaScript in the form of higher-order functions and function composition. Using higher-order functions we can imperatively decorate a piece of code in JavaScript.

What are decorators in JS?

Decorators provide a way to add both annotations and a meta-programming syntax for class declarations and members. Decorators are a stage 2 proposal for JavaScript and are available as an experimental feature of TypeScript. NOTE Decorators are an experimental feature that may change in future releases.

Where can decorators be applied to?

A Decorator is a special kind of declaration that can be applied to classes, methods, accessor, property, or parameter. Decorators are simply functions that are prefixed @expression symbol, where expression must evaluate to a function that will be called at runtime with information about the decorated declaration.

What is the return type of the decorator?

Decorators accept a function and return a function This function accept a number and returns either True or False depending on whether that number is prime or not.


1 Answers

Decorators only run once when the class is defined, but that doesn't mean that the definition-time logic can't set up the function to do stuff per-instance. In this case, you could memoize the value by defining an instance-specific property inside the prototye-level getter;

function once(target, name, descriptor) {
  let {get, writable, enumerable} = descriptor;
  if (typeof get === "function") {
    descriptor.get = function() {
      const value = get.apply(this, arguments);
      Object.defineProperty(this, name, {
        value,
        writable,
        enumerable
      });

      return value;
   }
  }
  return descriptor;
};
like image 74
loganfsmyth Avatar answered Oct 16 '22 09:10

loganfsmyth