17

Can't understand why I should use Reflect.get(obj, 'foo') instead of obj['foo'], or why the first one is useful as we can do the same thing using the good and old object bracket notation. Can someone please elaborate?

var obj = {foo: 'bar'};
obj['foo'];
Reflect.get(obj, 'foo');
darksoulsong
  • 11,559
  • 13
  • 42
  • 82
  • *"The `Reflect.get` method allows you to get a property on an object. It is like the property accessor syntax as a function."* – That's pretty much it. It's the same thing, but as a function. Can come in handy in functional programming. – deceze Jun 19 '17 at 20:26
  • @deceze but you can already create a closure anywhere you might need such a function... – Jon Jun 19 '17 at 20:27
  • @Jon Sure, but this one's built-in! … Yeah, that's all I got for that as well. – deceze Jun 19 '17 at 20:28

2 Answers2

23

Well, a pedantic answer to your question would be that they are entirely different: a property accessor returns a reference to a property, while Reflect.get returns its value.

From the practical standpoint that doesn't make any difference since property references are always dereferenced on the right side.

One practical usage of Reflect.get would be with its third argument, which, when combined with a Proxy, can be used to create different "views" of the same data.

let numbersView = obj => new Proxy(obj, {
    get(target, key, receiver) {
        return receiver(target[key])
    }
});

let decimal = x => String(x);

let english = x => {
    if (x === 1) return 'one';
    if (x === 2) return 'two';

};

let v = numbersView({
    a: 1,
    b: 2
});

console.log(Reflect.get(v, 'a', decimal))
console.log(Reflect.get(v, 'a', english))

This example is a bit made-up, but you got the idea.

georg
  • 204,715
  • 48
  • 286
  • 369
13

return Reflect.get(...arguments);

Calling the get trap for the bar as well.

const case1 = new Proxy({
    get foo() {
        console.log("The foo getter", this);
        return this.bar;
    },
    bar: 3
}, {
    get(target, property, receiver) {
        console.log("The Proxy get trap", ...arguments);
        return Reflect.get(...arguments);
    }
});
console.log(case1.foo);
> case1.foo
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The foo getter ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶bar ▶Proxy {bar: 3}
▶3

return target[property];

Using the unproxied object, target.

const case2 = new Proxy({
    get foo() {
        console.log("The foo getter", this);
        return this.bar;
    },
    bar: 3
}, {
    get(target, property, receiver) {
        console.log("The Proxy get trap", ...arguments);
        return target[property];
    }
});
console.log(case2.foo);
> case2.foo
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The foo getter ▶Proxy {bar: 3}
▶3

return receiver[property];

Using the proxied object, receiver, causing an infinity loop.

const case3 = new Proxy({
    get foo() {
        console.log("The foo getter", this);
        return this.bar;
    },
    bar: 3
}, {
    get(target, property, receiver) {
        console.log("The Proxy get trap", ...arguments);
        return receiver[property];
    }
});
console.log(case3.foo);
> case3.foo
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
▶The Proxy get trap ▶{bar: 3} ▶foo ▶Proxy {bar: 3}
……
Uncaught RangeError: Maximum call stack size exceeded

Now you get it.