Skip to main content

Proxy

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

  • 语法

const p = new Proxy(target, handler)

example
let user={
name:'aa',
age:12,
from:'china',
location:'haerbin'
}
let p=new Proxy(user,{
get(target,key,property){
console.log('get');
console.log(target);//目标对象
console.log(key);//要获取的key
console.log(property);//proxy对象
if(key.startsWith('_')){
console.log('error!不能访问私有对象!')
}else{
console.log(target[key]);
}
},
set(target,key,value){
console.log('set');
console.log(target);//目标对象
console.log(key);//要设置的key
console.log(value);//要设置成的value值
}
})
  • 转发代理
let target = {};
let p = new Proxy(target, {});

p.a = 37; // 操作转发到目标

console.log(target.a); // 37. 操作已经被正确地转发
  • 扩展构造函数

  • 操作dom节点

互换两个不同的元素的属性或类名

let view = new Proxy({
selected: null
}, {
set: function(obj, prop, newval) {
let oldval = obj[prop];

if (prop === 'selected') {
if (oldval) {
oldval.setAttribute('aria-selected', 'false');
}
if (newval) {
newval.setAttribute('aria-selected', 'true');
}
}

// 默认行为是存储被传入 setter 函数的属性值
obj[prop] = newval;

// 表示操作成功
return true;
}
});

let i1 = view.selected = document.getElementById('item-1');
console.log(i1.getAttribute('aria-selected')); // 'true'

let i2 = view.selected = document.getElementById('item-2');
console.log(i1.getAttribute('aria-selected')); // 'false'
console.log(i2.getAttribute('aria-selected')); // 'true'
  • 值修正及附加属性
let products = new Proxy({
browsers: ['Internet Explorer', 'Netscape']
}, {
get: function(obj, prop) {
// 附加一个属性
if (prop === 'latestBrowser') {
return obj.browsers[obj.browsers.length - 1];
}

// 默认行为是返回属性值
return obj[prop];
},
set: function(obj, prop, value) {
// 附加属性
if (prop === 'latestBrowser') {
obj.browsers.push(value);
return;
}

// 如果不是数组,则进行转换
if (typeof value === 'string') {
value = [value];
}

// 默认行为是保存属性值
obj[prop] = value;

// 表示成功
return true;
}
});

console.log(products.browsers); // ['Internet Explorer', 'Netscape']
products.browsers = 'Firefox'; // 如果不小心传入了一个字符串
console.log(products.browsers); // ['Firefox'] <- 也没问题,得到的依旧是一个数组

products.latestBrowser = 'Chrome';
console.log(products.browsers); // ['Firefox', 'Chrome']
console.log(products.latestBrowser); // 'Chrome'
  • 通过属性查找数组中的特定对象
let products = new Proxy([
{ name: 'Firefox' , type: 'browser' },
{ name: 'SeaMonkey' , type: 'browser' },
{ name: 'Thunderbird', type: 'mailer' }
], {
get: function(obj, prop) {
// 默认行为是返回属性值,prop ?通常是一个整数
if (prop in obj) {
return obj[prop];
}

// 获取 products 的 number; 它是 products.length 的别名
if (prop === 'number') {
return obj.length;
}

let result, types = {};

for (let product of obj) {
if (product.name === prop) {
result = product;
}
if (types[product.type]) {
types[product.type].push(product);
} else {
types[product.type] = [product];
}
}

// 通过 name 获取 product
if (result) {
return result;
}

// 通过 type 获取 products
if (prop in types) {
return types[prop];
}

// 获取 product type
if (prop === 'types') {
return Object.keys(types);
}

return undefined;
}
});

console.log(products[0]); // { name: 'Firefox', type: 'browser' }
console.log(products['Firefox']); // { name: 'Firefox', type: 'browser' }
console.log(products['Chrome']); // undefined
console.log(products.browser); // [{ name: 'Firefox', type: 'browser' }, { name: 'SeaMonkey', type: 'browser' }]
console.log(products.types); // ['browser', 'mailer']
console.log(products.number); // 3