JavaScript Proxy高级应用:5个元编程实战技巧
1. 基础属性拦截
实现属性访问控制:
const user = {
name: '张三',
age: 25
};
const userProxy = new Proxy(user, {
get(target, property) {
if (property === 'age') {
return `年龄: ${target[property]}`;
}
return target[property];
},
set(target, property, value) {
if (property === 'age' && value < 0) {
throw new Error('年龄不能为负数');
}
target[property] = value;
return true;
}
});
console.log(userProxy.age); // 年龄: 25
userProxy.age = 30; // 正常设置
userProxy.age = -5; // 抛出错误
const demoUser = { name: ‘李四’, age: 28 };
const demoProxy = new Proxy(demoUser, {
get(target, prop) {
if (prop === ‘age’) return `年龄: ${target[prop]}`;
return target[prop];
},
set(target, prop, value) {
if (prop === ‘age’ && value < 0) {
alert('年龄不能为负数');
return false;
}
target[prop] = value;
return true;
}
});
console.log(demoProxy.age); // 控制台查看效果
打开浏览器控制台查看效果
2. 数据验证代理
实现自动数据验证:
function createValidator(target, schema) {
return new Proxy(target, {
set(target, property, value) {
if (schema[property]) {
const isValid = schema[property](value);
if (!isValid) {
throw new Error(`无效的${property}值`);
}
}
target[property] = value;
return true;
}
});
}
const userSchema = {
name: val => typeof val === 'string',
age: val => Number.isInteger(val) && val >= 0
};
const validatedUser = createValidator({}, userSchema);
validatedUser.name = "张三"; // 成功
validatedUser.age = "30"; // 抛出错误
3. 自动依赖追踪
实现响应式数据:
const reactive = (obj, callback) => {
return new Proxy(obj, {
get(target, property) {
return target[property];
},
set(target, property, value) {
target[property] = value;
callback(property, value);
return true;
}
});
};
const state = reactive({ count: 0 }, (key, value) => {
console.log(`状态变化: ${key} = ${value}`);
});
state.count++; // 输出: 状态变化: count = 1
4. REST API封装
动态API调用:
const api = new Proxy({}, {
get(target, resource) {
return async function(params) {
const response = await fetch(`/api/${resource}`, {
method: 'POST',
body: JSON.stringify(params)
});
return response.json();
};
}
});
// 使用
const userData = await api.users({ id: 1 });
const productData = await api.products({ category: 'books' });
技术 | Object.defineProperty | Proxy |
---|---|---|
拦截能力 | 有限 | 全面 |
性能 | 较好 | 稍慢 |
兼容性 | ES5 | ES6 |
5. 电商实战:购物车代理
实现智能购物车:
const cart = {
items: [],
total: 0
};
const cartProxy = new Proxy(cart, {
set(target, property, value) {
if (property === 'items') {
// 自动计算总价
target.total = value.reduce((sum, item) =>
sum + (item.price * item.quantity), 0);
// 检查优惠条件
if (target.total > 1000) {
console.log('已达到满1000减100优惠条件!');
}
}
target[property] = value;
return true;
}
});
// 添加商品
cartProxy.items = [
{ id: 1, name: '商品A', price: 599, quantity: 2 },
{ id: 2, name: '商品B', price: 299, quantity: 1 }
];
console.log(cartProxy.total); // 1497
JavaScript Proxy为元编程提供了强大工具,特别适合数据验证、响应式系统、API封装等需要拦截和控制对象行为的场景。