# Proxy 实践

# Proxy 实例上的数组方法

当为数组创建代理时,调用代理上的数组方法时,可能会触发数组下标、length等属性的setget

(TODO: 这里会触发的原因应该是 C++ 源码里在实现这些方法时会访问/设置这些属性)

# push

const origin = ['a', 'b'];
const proxy = new Proxy(origin, {
    get(target, key, receiver) {
        const result = Reflect.get(target, key, receiver);
        console.log('get', key, result);
        return result;
    },
    set(target, key, value, receiver) {
        console.log('set', key, value);
        return Reflect.set(target, key, value, receiver);
    }
})
proxy.push('c');

// 结果
// get push function push() { [native code] }
// get length 2
// set 2 c
// set length 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

# pop

const origin = ['a', 'b'];
const proxy = new Proxy(origin, {
    get(target, key, receiver) {
        const result = Reflect.get(target, key, receiver);
        console.log('get', key, result);
        return result;
    },
    set(target, key, value, receiver) {
        console.log('set', key, value);
        return Reflect.set(target, key, value, receiver);
    },
    deleteProperty(target, key) {
        console.log('delete', key);
        return Reflect.deleteProperty(target, key);
    }
})
proxy.pop();

// 结果
// get pop function pop() { [native code] }
// get length 2
// get 1 b
// delete 1
// set length 1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

# shift

const origin = ['a', 'b'];
const proxy = new Proxy(origin, {
    get(target, key, receiver) {
        const result = Reflect.get(target, key, receiver);
        console.log('get', key, result);
        return result;
    },
    set(target, key, value, receiver) {
        console.log('set', key, value);
        return Reflect.set(target, key, value, receiver);
    },
    deleteProperty(target, key) {
        console.log('delete', key);
        return Reflect.deleteProperty(target, key);
    }
})
proxy.shift();

// 结果
// get shift function shift() { [native code] }
// get length 2
// get 0 a
// get 1 b
// set 0 b
// delete 1
// set length 1
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

# unshift

const origin = ['a', 'b'];
const proxy = new Proxy(origin, {
    get(target, key, receiver) {
        const result = Reflect.get(target, key, receiver);
        console.log('get', key, result);
        return result;
    },
    set(target, key, value, receiver) {
        console.log('set', key, value);
        return Reflect.set(target, key, value, receiver);
    }
})
proxy.unshift('c');

// 结果
// get unshift function unshift() { [native code] }
// get length 2
// get 1 b
// set 2 b
// get 0 a
// set 1 a
// set 0 c
// set length 3
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

# splice

const origin = ['a', 'b'];
const proxy = new Proxy(origin, {
    get(target, key, receiver) {
        const result = Reflect.get(target, key, receiver);
        console.log('get', key, result);
        return result;
    },
    set(target, key, value, receiver) {
        console.log('set', key, value);
        return Reflect.set(target, key, value, receiver);
    },
    deleteProperty(target, key) {
        console.log('delete', key);
        return Reflect.deleteProperty(target, key);
    }
})

proxy.splice(0, 1);
// 结果
// get splice function splice() { [native code] }
// get length 2
// get constructor function Array() { [native code] }
// get 0 a
// get 1 b
// set 0 b
// delete 1
// set length 1

proxy.splice(0, 1, 'c', 'd');
// 结果
// get splice function splice() { [native code] }
// get length 2
// get constructor function Array() { [native code] }
// get 0 a
// get 1 b
// set 2 b
// set 0 c
// set 1 d
// set length 3
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

# includes/indexOf/lastIndexOf

const origin = ['a', 'b'];
const proxy = new Proxy(origin, {
    get(target, key, receiver) {
        const result = Reflect.get(target, key, receiver);
        console.log('get', key, result);
        return result;
    },
});

proxy.includes('a')

// 结果
// get includes function includes() { [native code] }
// get length 2
// get 0 a

proxy.includes('c')

// 结果
// get includes function includes() { [native code] }
// get length 2
// get 0 a
// get 1 b
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23

indexOflastIndexOf同理,不再赘述。

需要注意的是,调用数组的这三个方法,并不能保证会get数组的每一项,若在某一项匹配到,则后续项将不会再get

# map

# forEach

# for of

# Proxy 的 ownKeys() 方法

Proxy 的ownKeys()可以拦截:

  • Object.getOwnPropertyNames()
  • Object.getOwnPropertySymbols()
  • Object.keys()
  • for...in循环

但是这些被拦截的不同的遍历方式在handler.ownKeys里统一使用Reflect.ownKeys()获取的值还是对应遍历方法原本的结果,这一点比较神奇。

const origin = {
    [Symbol('')]: '',
    a: 'a'
}

Object.defineProperty(origin, 'b', {
    value: 'b',
    enumerable: false
})

const handler = {
    ownKeys(target) {
        return Reflect.ownKeys(target);
    }
}

const proxy = new Proxy(origin, handler)

Reflect.ownKeys(proxy)               // [ 'a', 'b', Symbol() ]
Object.getOwnPropertyNames(proxy)    // [ 'a', 'b' ]
Object.getOwnPropertySymbols(proxy)  // [ Symbol() ]
Object.keys(proxy)                   // [ 'a' ]

for(let i in proxy) {
    console.log(i)                   // a
}
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
本站总访问量    次