Monthly Archives: October 2015


By Axel Rauschmayer

This blog post explains how to use ES6 Proxies to intercept method calls to an object.

Read chapter “Meta programming with proxies” in “Exploring ES6” for more information on Proxies.

The problem

You can intercept the operation get (getting property values) via a proxy and you can intercept the operation apply (calling a function), but there is no single operation for method calls that you could intercept. That’s because method calls are viewed as two separate operations: First a get to retrieve a function, then an apply to call that function.

The solution

If you want to intercept method calls, you must therefore intercept get and return a function that intercepts the function call. The following code demonstrates how that is done:

    function traceMethodCalls(obj) {
        let handler = {
            get(target, propKey, receiver) {
                const origMethod = target[propKey];
                return function (...args) {
                    let result = origMethod.apply(this, args);
                    console.log(propKey + JSON.stringify(args) + ' -> ' + JSON.stringify(result));
                    return result;
        return new Proxy(obj, handler);

I’m not using a Proxy for the latter task, I’m simply wrapping the original method with a function.

Let’s use the following object to try out traceMethodCalls():

    let obj = {
        add(x, y) {
            return x + y;
        multiply(x, y) {
            return x * y;

tracedObj is a traced version of obj. The first line after each method call is the output of console.log(), the second line is the result of the method call.

    > let tracedObj = traceMethodCalls(obj);
    > tracedObj.add(1,5)
    add[1,5] -> 6
    > tracedObj.multiply(2,7)
    multiply[2,7] -> 14

Obviously, this is not a very efficient solution. Once could, for example, cache methods. Furthermore, Proxies themselves have an impact on performance.

Source:: 2ality

Enumerability in ECMAScript 6

By Axel Rauschmayer

Enumerability is an attribute of object properties. This blog post explains how it works in ECMAScript 6.

Let’s first explore what attributes are.

Property attributes

Each object has zero or more properties. Each property has a key and three or more attributes, named slots that store the data of the property (in other words, a property is itself much like a JavaScript object or a record with fields in a database).

ECMAScript 6 supports the following attributes (as does ES5):

  • All properties have the attributes:
    • enumerable: Setting this attribute to false hides the property from some operations.
    • configurable: Setting this attribute to false prevents several changes to a property (attributes except value can’t be change, property can’t be deleted, etc.).
  • Normal properties (data properties, methods) have the attributes:
    • value: holds the value of the property.
    • writable: controls whether the property’s value can be changed.
  • Accessors (getters/setters) have the attributes:
    • get: holds the getter (a function).
    • set: holds the setter (a function).

You can retrieve the attributes of a property via Object.getOwnPropertyDescriptor(), which returns the attributes as a JavaScript object:

    > let obj = { foo: 123 };
    > Object.getOwnPropertyDescriptor(obj, 'foo')
    { value: 123,
      writable: true,
      enumerable: true,
      configurable: true }

This blog post explains how the attribute enumerable works in ES6. All other attributes and how to change attributes is explained in Sect. “Property Attributes and Property Descriptors” in “Speaking JavaScript”.

Constructs affected by enumerability

ECMAScript 5:

  • for-in loop: iterates over the string keys of own and inherited enumerable properties.
  • Object.keys(): returns the string keys of enumerable own properties.
  • JSON.stringify(): only stringifies enumerable own properties (with string keys).

ECMAScript 6:

  • Object.assign(): only copies enumerable own properties.
  • Reflect.enumerate(): returns all property keys that for-in iterates over.

for-in and Reflect.enumerate() are the only built-in operations where enumerability matters for inherited properties. All other operations only work with own properties.

Use cases for enumerability

Unfortunately, enumerability is quite an idiosyncratic feature. This section presents several use cases for it and argues that, apart from protecting legacy code from breaking, its usefulness is limited.

Use case: Hiding properties from the for-in loop

The for-in loop iterates over all non-enumerable properties of an object, own and inherited ones. Therefore, the attribute enumerable is used to hide properties that should not be iterated over. That was the reason for introducing enumerability in ECMAScript 1.

Non-enumerability in the language specification

Non-enumerable properties occur in the following locations in the language specification:

  • All prototype properties of built-in classes are non-enumerable:

        > Object.getOwnPropertyDescriptor(Object.prototype, 'toString').enumerable
  • All prototype properties of classes are non-enumerable:

        > Object.getOwnPropertyDescriptor(class {foo() {}}.prototype, 'foo').enumerable
  • In Arrays, length is not enumerable, which means that for-in only iterates over indices. (However, that can easily change if you add a property via assignment, which is makes it enumerable.)

        > Object.getOwnPropertyDescriptor([], 'length').enumerable
        > Object.getOwnPropertyDescriptor(['a'], '0').enumerable

The main reason for making all of these properties non-enumerable is to hide them (especially the inherited ones) from legacy code that uses the for-in loop or $.extend() (and similar operations that copy both inherited and own properties; see next section). Both operations should be avoided in ES6. Hiding them ensures that the legacy code doesn’t break.

Use case: Marking properties as not to be copied

Historical precedents

When it comes to copying properties, there are two important historical precedents that take enumerability into consideration:

Problems with this way of copying properties:

  • Turning inherited source properties into own target properties is rarely what you want. That’s why enumerability is used to hide inherited properties.

  • Which properties to copy and which not often depends on the task at hand, it rarely makes sense to have a single flag for everything. A better choice is to provide the copying operation with a predicate (a callback that returns a boolean) that tells it when to consider a property.

The only instance property that is non-enumerable in the standard library is property length of Arrays. However, that property only needs to be hidden due to it magically updating itself via other properties. You can’t create that kind of magic property for your own objects (short of using a Proxy).

ES6: Object.assign()

In ES6, Object.assign(target, source_1, source_2, ···) can be used to merge the sources into the target. Only the enumerable own properties of the sources are considered.

Object.assign() continues the tradition of Object.extend() and $.extend(), with regard to enumerability. Quoting Yehuda Katz:

Object.assign would pave the cowpath of all of the extend() APIs already in
circulation. We thought the precedent of not copying enumerable methods in
those cases was enough reason for Object.assign to have this behavior.

In other words: Object.assign() was created with an upgrade path from $.extend() (and similar) in mind. Its approach is cleaner than $.extend‘s, because it ignores inherited properties.

Note: don’t use Object.assign() to copy methods.
Prototype methods are non-enumerable. You therefore can’t use Object.assign() to copy methods from one prototype to another one. You could use it to copy methods from an object literal (which are enumerable) to a prototype. However, then the copied methods wouldn’t have the right enumerability. Furthermore, a method that uses super has a property that points to the object that hosts it. Object.assign() does not correctly update that property.

Marking properties as private

If you make a property non-enumerable, it can’t by seen by Object.keys() and the for-in loop, anymore. With regard to those mechanisms, the property is private.

However, there are several problems with this approach:

  • When copying an object, you normally want to copy private properties. That clashes making properties non-enumerable that shouldn’t be copied (see previous section).
  • The property isn’t really private. Getting, setting and several other mechanisms make no distinction between enumerable and non-enumerable properties.
  • When working with code either as source or interactively, you can’t immediately see whether a property is enumerable or not. A naming convention (such as prefixing property names with an underscore) is easier to discover.
  • You can’t use enumerability to distinguish between public and private methods, because methods in prototypes are non-enumerable by default.

Hiding own properties from JSON.stringify()

JSON.stringify() does not include properties in its output that are non-enumerable. You can therefore use enumerability to determine which own properties should be exported to JSON. This use case is similar to marking properties as private, the previous use case. But it is also different, because this is more about exporting and slightly different considerations apply. For example: Can an object be completely reconstructed from JSON?

An alternative for specifying how an object should be converted to JSON is to use toJSON():

    let obj = {
        foo: 123,
        toJSON() {
            return { bar: 456 };
    JSON.stringify(obj); // '{"bar":456}'

I find toJSON() cleaner than enumerability for the current use case. It also gives you more control, because you can export properties that don’t exist on the object.

Naming inconsistencies

In general, a shorter name means that only enumerable properties are considered:

  • Object.keys() ignores non-enumerable properties
  • Object.getOwnPropertyNames() lists all property names

However, Reflect.keys() deviates from that rule, it ignores enumerability and returns the keys of all properties. Additionally, starting with ES6, the following distinction is made:

  • Property keys are either strings or symbols.
  • Property names are only strings.

Therefore, a better name for Object.keys() would now be Object.names().

Looking ahead

It seems to me that enumerability is only suited for hiding properties from the for-in loop and $.extend() (and similar operations). Both are legacy features, you should avoid them in new code. As for the other use cases:

  • I don’t think there is a need for a general flag specifying whether or not to copy a property.
  • Non-enumerability does not work well as a way to keep properties private.
  • The toJSON() method is more powerful and explicit than enumerability when it comes to controlling how to convert an object to JSON.

I’m not sure what the best strategy is for enumerability going forward. If, with ES6, we had started to pretend that it didn’t exist (except for making prototype properties non-enumerable so that old code doesn’t break), we might eventually have been able to deprecate enumerability. However, Object.assign() considering enumerability runs counter that strategy (but it does so for a valid reason, backward compatibility).

In my own ES6 code, I’m not using enumerability, except for classes whose prototype methods are non-enumerable.

Lastly, when using an interactive command line, I occasionally miss an operation that returns all property keys of an object, not just the own ones (Reflect.keys) or not just string-valued enumerable ones (Reflect.enumerate). Such an operation would provide a nice overview of the contents of an object.

Feel free to disagree with what I have written in this blog post and let us know in the comments below. My opinion about enumerability is still evolving, because it’s such a confusing feature.

Source:: 2ality

ES6: methods versus callbacks

By Axel Rauschmayer

There is a subtle difference between an object with methods and an object with callbacks.

An object whose properties are methods

The this of a method is the receiver of the method call (e.g. obj if the method call is obj.m(···)).

For example, you can use the WHATWG streams API as follows:

    let surroundingObject = {
        surroundingMethod() {
            let obj = {
                data: 'abc',
                start(controller) {
                    console.log(; // abc (*)
                    this.pull(); // (**)
                pull() {
                cancel() {
            let stream = new ReadableStream(obj);

That is, obj is an object whose properties start, pull and cancel are methods. Accordingly, these methods can use this to access object-local state (line *) and to call each other (line **).

An object whose properties are callbacks

The this of an arrow function is the this of the surrounding scope (lexical this). Arrow functions make great callbacks, because that is the behavior you normally want for callbacks (real, non-method functions). A callback shouldn’t have its own this that shadows the this of the surrounding scope.

If the properties start, pull and cancel are arrow functions then they pick up the this of surroundingMethod() (their surrounding scope):

    let surroundingObject = {
        surroundingData: 'xyz',
        surroundingMethod() {
            let obj = {
                start: controller => {
                    console.log(this.surroundingData); // xyz (*)
                pull: () => {
                cancel: () => {
            let stream = new ReadableStream(obj);
    let stream = new ReadableStream();

If the output in line * surprises you then consider the following code:

    let obj = {
        foo: 123,
        bar() {
            let f = () => console.log(; // 123
            let o = {
                p: () => console.log(, // 123

Inside method bar(), f and o.p work the same, because both arrow functions have the same surrounding lexical scope, bar(). The latter arrow function being surrounded by an object literal does not change that.

Further reading

Chapter “Callable entities in ECMAScript 6” in ”Exploring ES6”.

Source:: 2ality