Proxy在计算机领域是一个很普遍的概念,中文通常翻译为代理,“代理”一般用于描述某人或某事代表他人行事。常见的概念有Proxy Server(代理服务器)、Reverse Proxy(反向代理)、Proxy Pattern(代理模式)等。
为了理解Proxy,我们先问自己几个问题:
理解了上面两个问题,学习Javascript的Proxy就简单多了。
ES6中也出现了Proxy,和其他的Proxy类似,ES6中的Proxy也用于代理某个东西,同样我们需要弄懂几个问题:
创建一个proxy:
const p = new Proxy(target, handler);
target
:是被代理的对象,可以是对象、数组、方法、构造函数class甚至是另外一个proxy,总之可以是任何JavaScript对象;
handler
:一个对象,属性是各种控制或修改target
基本行为的方法;
比如用户未设置头像则返回默认头像可以这么写:
const user = { name: 'bruce' };
const userProxy = new Proxy(user, {
get: (obj, prop) => {
if (prop === 'avatar') {
if (!obj.avatar) {
return 'https://avatar-static.segmentfault.com/100/035/1000355095-5b3c339ebdbe1_big64';
}
}
return obj[prop];
}
});
console.log(userProxy.avatar); // https://avatar-static···
或者我们可以实现alert换行显示多条信息:
const myAlert = new Proxy(alert, {
apply: (target, thisArg, argumentsList) => {
const msg = argumentsList.join('\n');
target(msg);
}
});
myAlert('haha', 'lala');
React源码中也有proxy的应用,用proxy来统一管理event:
/** Proxying after everything set on SyntheticEvent
* to resolve Proxy issue on some WebKit browsers
* in which some Event properties are set to undefined (GH#10010)
*/
{
var isProxySupported = typeof Proxy === 'function' &&
// https://github.com/facebook/react/issues/12011
!Object.isSealed(new Proxy({}, {}));
if (isProxySupported) {
/*eslint-disable no-func-assign */
SyntheticEvent = new Proxy(SyntheticEvent, {
construct: function (target, args) {
return this.apply(target, Object.create(target.prototype), args);
},
apply: function (constructor, that, args) {
return new Proxy(constructor.apply(that, args), {
set: function (target, prop, value) {
if (prop !== 'isPersistent' && !target.constructor.Interface.hasOwnProperty(prop) && shouldBeReleasedProperties.indexOf(prop) === -1) {
!(didWarnForAddedNewProperty || target.isPersistent()) ? warning_1(false, "This synthetic event is reused for performance reasons. If you're " + "seeing this, you're adding a new property in the synthetic event object. " + 'The property is never released. See ' + 'https://fb.me/react-event-pooling for more information.') : void 0;
didWarnForAddedNewProperty = true;
}
target[prop] = value;
return true;
}
});
}
});
/*eslint-enable no-func-assign */
}
}