Proxy
Proxy 是 ES6 中新增的一个功能,用于创建一个对象的代理,从而实现对对象的拦截、修改、增加等操作。下面详细介绍 Proxy 的使用方法。
基本使用
我们可以通过 Proxy(target, handler) 方法来创建一个代理对象,其中 target 是需要被代理的对象,handler 是一个对象,用于定义代理的行为。下面是一个简单的例子:
javascriptCopy code
let obj = new Proxy({}, {
get: function(target, propKey) {
console.log('get ' + propKey);
return target[propKey];
},
set: function(target, propKey, value) {
console.log('set ' + propKey + ' = ' + value);
target[propKey] = value;
return true;
}
});
上面的代码创建了一个空对象的代理 obj,并定义了代理的行为。当我们通过 obj.xxx 来访问或修改对象的属性时,代理会拦截这个操作,并在控制台打印相应的信息。
javascriptCopy code
obj.foo = 'bar';
// set foo = bar
console.log(obj.foo);
// get foo
// bar
get
get 方法用于拦截对象属性的读取操作,它接受两个参数:
target:需要被代理的对象;propKey:属性名。 当我们通过obj.xxx来访问对象的属性时,如果该属性存在,get方法会被调用,并返回属性的值。如果该属性不存在,get方法会返回undefined。
javascriptCopy code
let obj = new Proxy({foo: 'bar'}, {
get: function(target, propKey) {
console.log('get ' + propKey);
return target[propKey];
}
});
console.log(obj.foo);
// get foo
// bar
console.log(obj.baz);
// get baz
// undefined
set
set 方法用于拦截对象属性的设置操作,它接受三个参数:
target:需要被代理的对象;propKey:属性名;value:属性值。 当我们通过obj.xxx = yyy来修改对象的属性时,set方法会被调用,并设置属性的值。如果set方法返回false,表示修改失败。
javascriptCopy code
let obj = new Proxy({}, {
set: function(target, propKey, value) {
console.log('set ' + propKey + ' = ' + value);
target[propKey] = value;
return true;
}
});
obj.foo = 'bar';
// set foo = bar
obj.foo = 'baz';
// set foo = baz
has
has 方法用于判断对象是否有某个属性,它接受两个参数:
target:需要被代理的对象;propKey:属性名。 当我们通过propKey in obj来判断对象是否有某个属性时,has方法会被调用,并返回一个布尔值。
javascriptCopy code
let obj = new Proxy({foo: 'bar'}, {
has: function(target, propKey) {
console.log('has ' + propKey);
return propKey in target;
}
});
console.log('foo' in obj);
// has foo
// true
console.log('baz' in obj);
// has baz
// false
deleteProperty
deleteProperty 方法用于拦截对象属性的删除操作,它接受两个参数:
target:需要被代理的对象;propKey:属性名。 当我们通过delete obj.xxx来删除对象的属性时,deleteProperty方法会被调用,并删除相应的属性。如果deleteProperty方法返回false,表示删除失败。
javascriptCopy code
let obj = new Proxy({foo: 'bar'}, {
deleteProperty: function(target, propKey) {
console.log('delete ' + propKey);
delete target[propKey];
return true;
}
});
delete obj.foo;
// delete foo
apply
apply 方法用于拦截函数的调用,它接受三个参数:
target:需要被代理的函数;thisArg:函数的上下文对象;argumentsList:函数的参数列表。 当我们通过obj.xxx()来调用对象的方法时,apply方法会被调用,并执行相应的操作。如果apply方法返回的是一个函数,那么这个函数将被作为调用结果返回。
javascriptCopy code
let obj = new Proxy(function(x, y) {
return x + y;
}, {
apply: function(target, thisArg, argumentsList) {
console.log('apply ' + argumentsList);
return target.apply(thisArg, argumentsList);
}
});
console.log(obj(1, 2));
// apply 1,2
// 3
construct
construct 方法用于拦截 new 操作符,它接受两个参数:
target:需要被代理的函数;argumentsList:构造函数的参数列表。 当我们通过new obj()来创建对象时,construct方法会被调用,并执行相应的操作。如果construct方法返回的是一个对象,那么这个对象将被作为实例返回。
javascriptCopy code
let obj = new Proxy(function(x, y) {
this.x = x;
this.y = y;
}, {
construct: function(target, argumentsList) {
console.log('construct ' + argumentsList);
return new target(...argumentsList);
}
});
let instance = new obj(1, 2);
console.log(instance.x, instance.y);
// construct 1,2
// 1 2
实战应用
Proxy 的应用非常广泛,可以用来实现数据的双向绑定、实现数据的缓存、实现数据的节流等功能。下面是一个简单的例子,用来实现数据的缓存。
javascriptCopy code
function getData(key) {
return localStorage.getItem(key);
}
function setData(key, value) {
localStorage.setItem(key, value);
}
let cache = new Proxy({}, {
get: function(target, propKey) {
console.log('get ' + propKey);
return getData(propKey);
},
set: function(target, propKey, value) {
console.log('set ' + propKey + ' = ' + value);
setData(propKey, value);
return true;
}
});
cache.foo = 'bar';
// set foo = bar
console.log(cache.foo);
// get foo
// bar
上面的代码通过 Proxy 实现了一个简单的缓存功能,每当我们通过 cache.xxx 来访问或修改缓存时,代理会拦截相应的操作,并将数据存储到本地存储中。