JavaScript:Reflect.get() 和 obj['foo'] 之间的区别

问题描述 投票:0回答:2

无法理解为什么我应该使用

Reflect.get(obj, 'foo')
而不是
obj['foo']
,或者为什么第一个很有用,因为我们可以使用良好且旧的对象括号表示法做同样的事情。有人可以详细说明一下吗?

var obj = {foo: 'bar'};
obj['foo'];
Reflect.get(obj, 'foo');
javascript reflection
2个回答
25
投票

嗯,对你的问题的迂腐答案是它们完全不同:属性访问器返回属性的引用,而

Reflect.get
返回其

从实际角度来看,这没有任何区别,因为属性引用总是在右侧取消引用。

Reflect.get
的一个实际用法是使用它的第三个参数,当与
Proxy
结合使用时,可以用于创建相同数据的不同“视图”。

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))

这个例子有点虚构,但你已经明白了。


20
投票

return Reflect.get(...arguments);

Reflect.get
指吸气剂(如果有的话)。
foo
getter 被赋予代理对象
receiver
(
receiver === case1
),用于其
this
。意思是,也调用了
get
bar
陷阱。

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];

使用未代理的对象,

target
。这也会触发
foo
getter,但请注意:
this
getter 的
foo
是未代理的对象
target
。未调用
get
bar
陷阱。

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 ▶{bar: 3}
▶3

return receiver[property];

使用代理对象,

receiver
(
receiver === case3
)。
receiver[property]
指的是
get
陷阱,而不是吸气剂,导致无限循环。

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

现在你明白了。


使用哪个

不明白为什么我应该使用

Reflect.get(obj, 'foo')
而不是
obj['foo']

虽然使用

Reflect
动词是
Proxy
陷阱实现的惯用法,但实际上没有 should。这取决于您的用例。如果您的
target
(“未代理”)对象没有 getter,或者您对其 getter 正在访问的属性(“辅助属性访问”)不感兴趣,那么您可能不需要看起来很花哨的
Reflect
。另一方面,如果您想触发所有类型的属性访问(主要或次要)的陷阱,您将需要
Reflect

对于我来说,我始终坚持

return Reflect.get(...arguments);

© www.soinside.com 2019 - 2024. All rights reserved.