持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第11天,点击查看活动详情
Proxy对象
Proxy对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。 Proxy(target, handler),两个参数
- target:要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
- handler:要使用Proxy包装的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。handler对象是一个容纳一批特定属性的占位符对象。它包含有Proxy的各个捕获器(trap)。
handler对象的方法:
- handler.getPrototypeOf()是Object.getPrototypeOf方法的捕捉器。getPrototypeOf(obj)方法是获取一个对象的原型,
const object1 = {}
const handler = {
getPrototypeOf:function(target){ //参数target是代理的对象
console.log('getProto');
return {} // 必须返回一个对象或null
}
};
const p = new Proxy(object1, handler);
Object.getPrototypeOf(p) // 这里会打印出: 'getProto'
- handler.setPrototypeOf()是Object.setPrototypeOf方法的捕捉器。可以监听到Object.setPrototypeOf()和Reflect.setPrototypeOf()
var handlerReturnsFalse = {
setPrototypeOf(target, newProto) {//参数target是代理的对象,newProto对象新原型或为null.
return false; // 这里显示返回false则所有对于圆形的设置都会失败,及原型不会修改。但是需要注意到,在object调用时会返回一个类型错误,Reflect则会返回false。
}
};
var newProto = {}, target = {};
var p1 = new Proxy(target, handlerReturnsFalse);
Object.setPrototypeOf(p1, newProto); // throws a TypeError
Reflect.setPrototypeOf(p1, newProto); // returns false
- handler.isExtensible()是Object.isExtensible()方法的捕捉器。isExtensible()方法是判定对象是否可以扩展。(是否可以在它上面添加新的属性)。
var p = new Proxy({}, {
isExtensible: function(target) { //参数target是代理的对象
console.log('called');
return true; // 也可以 return 1; 等表示为 true 的值,这里必须返回一个布尔类型,
// 或者可以转换为布尔类型的值,返回true是就是可以,返回false时会在object报错。
}
});
console.log(Object.isExtensible(p)); // "called"
// true
-
handler.preventExtensions()是Object.preventExtensions方法的捕捉器。preventExtensions()方法让一个对象变的不可扩展,也就是永远不能再添加新的属性。
-
handler.getOwnPropertyDescriptor()是Object.getOwnPropertyDescriptor方法的捕捉器.Object.getOwnPropertyDescriptor()方法返回指定对象上一个自有属性对应的属性描述符。(自有属性指的是直接赋予该对象的属性,不需要从原型链上进行查找的属性) Object.getOwnPropertyDescriptor(obj, prop)
const object1 = {
property1: 42
};
const descriptor1 = Object.getOwnPropertyDescriptor(object1, 'property1');
console.log(descriptor1);// {configurable: true,enumerable: true,value: 42,writable: true}
- handler.defineProperty()是Object.defineProperty 方法的捕捉器。 Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
var p = new Proxy({}, {
defineProperty: function(target, prop, descriptor) {
console.log('called: ' + prop);
return true;
}
});
var desc = { configurable: true, enumerable: true, value: 10 };
Object.defineProperty(p, 'a', desc); // "called: a"
- handler.has()是in操作符的捕捉器。
- handler.get()属性读取操作的捕捉器。
var p = new Proxy({}, {
get: function(target, prop, receiver) { // receiver 是Proxy 或者继承 Proxy 的对象
console.log("called: " + prop);
return 10; // 这里可以返回任意值,需要注意如果该对象的属性不可修改时,必须返回与对象属性相同的值,不然会报错。
}
});
console.log(p.a); // "called: a"
// 10
- handler.set()方法是设置属性值操作的捕获器。
var p = new Proxy({}, {
set: function(target, prop, value, receiver) { // target目标对象。
// property将被设置的属性名或 Symbol
// value新属性值。
// receiver最初被调用的对象。通常是 proxy 本身,但 handler 的 set 方法也有可能在原型链上,或以其他方式被间接地调用(因此不一定是 proxy 本身)。
target[prop] = value;
console.log('property set: ' + prop + ' = ' + value);
return true; // set()方法应当返回一个布尔值。true表示成功设置。
}
})
p.a = 10; // "property set: a = 10"
console.log(p.a); // 10
- handler.deleteProperty()方法用于拦截对对象属性的 delete 操作。
var p = new Proxy({}, {
deleteProperty: function(target, prop) { // target目标对象。prop要删除的属性。
console.log('called: ' + prop);
return true; // 方法应当返回一个布尔值。true表示删除设置。
}
});
delete p.a;
- handler.ownKeys()方法用于拦截 Reflect.ownKeys(),Object.getOwnPropertyNames(), ,Object.getOwnPropertySymbols() ,Object.keys()
var p = new Proxy({}, {
ownKeys: function(target) {
console.log('getkeys');
return ['a', 'b', 'c'];
}
});
console.log(Object.getOwnPropertyNames(p)) // getkeys // ['a', 'b', 'c'];
- handler.apply()函数调用操作的捕捉器。会拦截的操作proxy(...args), Function.prototype.apply() 和 Function.prototype.call(),Reflect.apply()
var p = new Proxy(function() {}, {
apply: function(target, thisArg, argumentsList) { // target,目标对象(函数)。
// thisArg, 被调用时的上下文对象。
// argumentsList被调用时的参数数组。
console.log('called: ' + argumentsList.join(', '));
return argumentsList[0] + argumentsList[1] + argumentsList[2];
}
});
console.log(p(1, 2, 3)); // "called: 1, 2, 3"
// 6
- ` handler.construct() 方法用于拦截 new 操作符。
var p = new Proxy(function() {}, {
construct: function(target, argumentsList, newTarget) {
// target,目标对象。
// argumentsList 参数列表。
// newTarget 最初被调用的构造函数。
console.log('call: ' + argumentsList.join(', '));
return { value: argumentsList[0] * 10 }; // 必须返回一个对象,否则会报错。
}
});
console.log(new p(1).value); // "call: 1"
// 10