3

Using Babel to transpile the following es7 code:

let obj = {
  @decorate
  prop: 10
}

let decorate = ( object, propertyName, desc ) => desc

When decorate is called, the property descriptor desc contains a method named initializer, that returns the value of obj.prop when executed.

Is the initializer method part of the es7 Decorator specification, or is this purely a side effect of Babel converting to es5?

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
Mark Lundin
  • 328
  • 1
  • 7

2 Answers2

2

es7 Decorator specification

Notice there is neither ES7 yet nor a specification for decorators. There's a draft, a harmony proposal, for how the language may be extended.

When decorate is called, the property descriptor desc contains a method named initializer

That's a bit odd. From the current proposal I would have expected that the decorator is always called with the property descriptor for that property, which would be

{value: 10, writable: true, enumerable: true, configurable: true}

for your example. However, the examples in the draft do only outline decorators for methods (and accessor properties), both on classes and object literals, but not for value properties.

Is the initializer method part of the Decorator proposal?

Not currently, but there is a INITIALIZER_INTEROP.md file in their repository which outlines interoperability of decorators with the PropertyInitialisers from the class properties proposal (which is an unfinished draft, but already implemented in babel, as well). It does indeed use static decorators which are given descriptors with an initializer function that would be evaluated to initialise the instance property in (before) the constructor.

is this purely a side effect of Babel converting to es5?

Not really. IMO it's just a bug, probably stemming from how babel transpiles class properties, which makes them look the same as value properties on an object literal.

Knu
  • 14,806
  • 5
  • 56
  • 89
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Thanks, as I expected. Safe to assume that you cannot rely on `initializer` as a method to return the value – Mark Lundin Jul 15 '15 at 16:04
  • 1
    I think it would be save to assume that an `initializer` always returns the value, but in fact you indeed cannot rely on anything from babel's experimental features. – Bergi Jul 15 '15 at 16:10
1

The initializer function mostly makes sense if you consider the proposal-class-fields TC39 proposal.

Consider the following code:

class C {
  prop = {};
}

const a = new C()
const b = new C()

console.log(a.prop === b.prop)

You would expect the output to be false.

For that reason, the "value" of the property cannot be stored as a static value, but must instead be encoded as a function that returns a new value (here, an empty object) every time.

That code gets transpiled to something equivalent to:

class C {
    constructor () {
        const propName = 'prop'
        const propDesc = Object.getOwnPropertyDescriptor(this.constructor.prototype, propName)
        this[propName] = propDesc.initializer.call(this)
    }
}

This also allows you to reference this while declaring other instance variables (still in the context of that proposal):

class C {
    entries = [ 1, 2, 3 ];
    count = this.entries.length;
}

Since class C is basically syntactic sugar for writing C.prototype, decorators on class properties, are actually the same as decorators on object properties (the object being the prototype in this case).

The initializer pattern allows for a single way of writing decorators in both these cases.

Mat
  • 1,022
  • 2
  • 9
  • 24