Lazy evaluation

Alex Kodat alexkodat at
Wed Sep 13 13:32:08 UTC 2017

Also, FWIW,  since we’re talking about nanoseconds of performance, here, I think slightly better than:

    return this.#random || (this.#random = Math.random());


    return (this.#random === undefined) ? this.#random = Math.random() : this.#random;

This is because in the former, the compiled code has to determine whether this.#random is coercible into a Boolean. At the very least, it has to do an "Is this an object and, if so, not undefined ==> true" test. From first principles, the ternary expression is going to be more efficient. It simply checks if the value at this.#random is the same as the global undefined value and, if not, returns that value. No extra tests necessary.

And at least with V8 theory == practice in this case (at least in all my tests). And yes, we're talking nanosecond here.

While this looks a bit like the null propagation operator would be applicable, it's really not. 

Also FWIW, if you get tired of seeing/typing undefined, we add _ to the global object which means the above can be written as:

    return (this.#random === _) ? this.#random = Math.random() : this.#random;

You might think that this would perform worse than the undefined but, in fact, for V8 it's identical -- undefined and _ are both just properties of the global object. I think this reads especially well in function calls where you want an undefined placeholder

  fooey(_, "whatever");

Visually, _ just says undefined to me.

Alex Kodat

From: es-discuss [mailto:es-discuss-bounces at] On Behalf Of Andrea Giammarchi
Sent: Wednesday, September 13, 2017 2:31 AM
To: Steve Fink <sphink at>
Cc: es-discuss at
Subject: Re: Lazy evaluation

> The properties already existed, so defineProperty shouldn't modify the order IIUC

well, nope. the property existed in the prototype, not in the object.

anyway, I guess private properties, that are a possible solution, will be transpiled through a WeakMap so that most likely anything discussed in here won't make sense and the future code would look like the following

class A {
  get random() {
    return this.#random ||
          (this.#random = Math.random());

// transpiled
var A = function (wm) {
  function A() {
    wm.set(this, {random: void 0});
      random: {
        configurable: true,
        get: function () {
          return wm.get(this).random ||
                (wm.get(this).random = Math.random());
  return A;
}(new WeakMap);

More information about the es-discuss mailing list