Proxy/Reflect

this 和 receiver

Proxy 的 get() 里的 this 和 receiver

Proxy 的get()方法里的receiver总是指向原始的读操作所在的那个对象。

常规情况下,receiver即为 Proxy 实例。

const origin = {
    a: 'a'
};
const proxy = new Proxy(origin, {
    get(target, key, receiver) {
        // 读操作是在 proxy 对象上进行的,因此 receiver === proxy
        console.log('receiver === proxy -->', receiver === proxy);
        return Reflect.get(target, key, receiver);
    }
});

proxy.a;

// 结果
// receiver === proxy --> true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

而当 Proxy 实例位于读操作所在对象的原型链上时,Proxy 的get()方法里的receiver就会指向读操作所在的对象。

const origin = {
    a: 'a'
};
const proxy = new Proxy(origin, {
    get(target, key, receiver) {
        // 读操作是在 child 对象上进行的,因此 receiver === child
        console.log('receiver === proxy -->', receiver === proxy);
        console.log('receiver === child -->', receiver === child);
        return Reflect.get(target, key, receiver);
    }
});

const child = Object.create(proxy);

child.a;

// 结果
// receiver === proxy --> false
// receiver === child --> true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Proxy 的 set() 里的 receiver

类似于get(),Proxy 的set()里的receiver指的是原始的写操作所在的那个对象。

const origin = {
    a: 'a'
};
const proxy = new Proxy(origin, {
    set(target, key, value, receiver) {
        // 写操作是在 proxy 对象上进行的,因此 receiver === proxy
        console.log('receiver === proxy -->', receiver === proxy);
        return Reflect.set(target, key, value, receiver);
    }
});

proxy.a = 'b';

// 结果
// receiver === proxy --> true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const origin = {
    a: 'a'
};
const proxy = new Proxy(origin, {
    set(target, key, value, receiver) {
        // 写操作是在 child 对象上进行的,因此 receiver === child
        console.log('receiver === proxy -->', receiver === proxy);
        console.log('receiver === child -->', receiver === child);
        return Reflect.set(target, key, value, receiver);
    }
});

const child = Object.create(proxy);

child.a = 'b';

// 结果
// receiver === proxy --> false
// receiver === child --> true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Proxy 的 get()/set() 里的 this

无论proxy实例是否位于读/写操作所在对象的原型链上,Proxy 的get/set方法里的this,都指向定义get/set时所在的那个对象。

const origin = {
    a: 'a'
};

const handler = {
    get(target, key, receiver) {
        console.log('this === handler -->', this === handler);
        return Reflect.get(target, key, receiver);
    }
}

const proxy = new Proxy(origin, handler);

proxy.a;

// 结果
// this === handler --> true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

set同理。在实际应用中,基本上不会在get/set里使用this

Proxy 的 get() 返回的函数内的 this

Proxy 里get()方法返回的若是函数的话,则该函数会自动绑定thisproxy实例,无论这个函数来自于哪里。

const origin = {
    fn() {
        console.log('origin.fn:');
        console.log('this === proxy -->', this === proxy);
    },
    fn1() {
        console.log('origin.fn1:');
        console.log('this === proxy -->', this === proxy);
    }
}

const instrumentation = {
    fn() {
        console.log('instrumentation.fn: ');
        console.log('this === proxy -->', this === proxy);
    }
}

const globalFn2 = function() {
    console.log('globalFn2: ');
    console.log('this === proxy -->', this === proxy);
}

const proxy = new Proxy(origin, {
    get(target, key, receiver) {
        if (key === 'fn') {
            // 即使不传入 receiver,结果仍一样
            return Reflect.get(instrumentation, key, receiver)
        }
        if (key === 'fn1') {
            // 即使不传入 receiver,结果仍一样
            return Reflect.get(target, key, receiver);
        }
        if (key === 'fn2') {
            return globalFn2;
        }
    }
})

proxy.fn();

// 结果
// instrumentation.fn:
// this === proxy --> true

proxy.fn1();

// 结果
// origin.fn1:
// this === proxy --> true

proxy.fn2();

// 结果
// globalFn2:
// this === proxy --> true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

Reflect.get() 里的 this 和 receiver

origingetter函数时,调用Reflect.get()不传入第三个参数receiver,则origin里的getter函数里的this指向origin

const origin = {
    a: 'a',
    b: 'b',
    get c() {
        console.log('this === receiver -->', this === receiver);
        console.log('this === origin -->', this === origin);
        return this.a + this.b;
    }
}

const receiver = {
    a: 1,
    b: 2
}

console.log(Reflect.get(origin, 'c'))

// 结果
// this === receiver --> false
// this === origin --> true
// ab
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

origingetter函数时,调用Reflect.get()若传入第三个参数receiver,则origin里的getter函数里的this指向receiver

const origin = {
    a: 'a',
    b: 'b',
    get c() {
        console.log('this === receiver -->', this === receiver);
        console.log('this === origin -->', this === origin);
        return this.a + this.b;
    }
}

const receiver = {
    a: 1,
    b: 2
}

console.log(Reflect.get(origin, 'c', receiver))

// 结果
// this === receiver --> true
// this === origin --> false
// 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

Reflect.set() 里的 this 和 receiver

同理,当originsetter函数时,调用Reflect.set()若不传入第四个参数receiver,则origin里的setter函数里的this指向origin;如传入第四个参数receiver,则origin里的setter函数里的this指向receiver

const origin = {
    a: 'a',
    b: 'b',
    set c(value) {
        console.log('this === receiver -->', this === receiver);
        console.log('this === origin -->', this === origin);
    }
}

const receiver = {
    a: 1,
    b: 2
}

Reflect.set(origin, 'c', 'c')

// 结果
// this === receiver --> false
// this === origin --> true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
const origin = {
    a: 'a',
    b: 'b',
    set c(value) {
        console.log('this === receiver -->', this === receiver);
        console.log('this === origin -->', this === origin);
    }
}

const receiver = {
    a: 1,
    b: 2
}

Reflect.set(origin, 'c', 'c', receiver)

// 结果
// this === receiver --> true
// this === origin --> false
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19