Proxy

  • Proxy 是代理, 和 Object.defineproperty 完全不同
  • Object.defineProperty是用于监听属性,而Proxy是监听整个对象
  • Proxy 代理了对象去进行操作
  • Object.defineProperty则是数据劫持
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    let target = {
    a: 1,
    b: 2
    }
    let proxy = new Proxy(target, {
    get(target, prop) {
    return target
    },
    set(target, prop, value) {
    target[prop] = value;
    }
    });
    target.b = 3
    console.log(proxy, target);

Proxy.revocable()

  • Proxy.revocable(target, handler)
  • Proxy.revocable()方法可以用来创建一个可撤销的代理对象,其返回一个包含了代理对象本身和它的撤销方法的可撤销Proxy对象。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
handler.getPrototypeOf(): Object.getPrototypeOf方法的捕捉器 // 获取原型
handler.setPrototypeOf(): Object.setPrototypeOf方法的捕捉器 // 设置原型
handler.isExtensible(): Object.isExtensible方法的捕捉器 // 获取对象的可拓展性
handler.preventExtensions(): Object.preventExtensions方法的捕捉器 // 禁止拓展对象
handler.getOwnPropertyDescriptor(): Object.getOwnPropertyDescriptor方法的捕捉器 // 获取自有属性
handler.defineProperty(): Object.defineProperty方法的捕捉器 // 拦截对象操作
handler.has(): in操作符的捕捉器 // 判断是否是自身属性 obj.hasOwnProperty(')
handler.get(): 属性读取操作的捕捉器 // 'a' in obj obj.a
handler.set(): 属性设置操作的捕捉器 // obj.a = 3
handler.deleteProperty(): delete操作符的捕捉器 // 可删除 delete obj.a
// [Enumerate] 可枚举
handler.ownKeys(): Reflect.ownKeys、Object.getOwnPropertyNames、Object.keys、Object.getOwnPropertySymbols方法的捕捉器 // 获取键集合
handler.apply(): 函数调用操作的捕捉器
handler.construct(): new操作符的捕捉器
1
2
3
4
5
6
7
8
9
10
11
12
var revocable = Proxy.revocable({}, {
get: function(target, key) {
return `[[ ${key} ]]`;
}
});
var proxy = revocable.proxy;
console.log(proxy.example); // [[ example ]]
revocable.revoke();
// console.log(proxy.example); // 抛出 TypeError
// proxy.example = 1; // 抛出 TypeError
// delete proxy.example; // 抛出 TypeError
// typeof proxy // "object",因为 typeof 不属于可代理操作

手写一个Proxy

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
function MyProxy(target, handler) {
let _target = deepClone(target);
Object.keys(_target).forEach((key) => {
Object.defineProperty(_target, key, {
get: function () {
return handler.get && handler.get(target, key);
},
set: function (newVal) {
handler.set && handler.set(target, key, newVal);
}
})
})
return _target;

function deepClone(org, tar) {
var tar = tar || {},
toStr = Object.prototype.toString,
arrType = '[object Array]';
for (var key in org) {
if (org.hasOwnProperty(key)) {
if (typeof (org[key]) === 'object' && org[key] !== null) {
tar[key] = toStr.call(org[key]) === arrType ? [] : {};
deepClone(org[key], tar[key]);
} else {
tar[key] = org[key];
}
} else {
tar[key] = org[key];
}
}
return tar;
}
}

let target = { a: 1, b: 2 }
let proxy = new MyProxy(target, {
get(target, prop) {
return target[prop]
},
set(target, prop, value) {
target[prop] = value;
}
});
console.log(proxy.a);
proxy.b = 3

仓库地址