Proxy、Reflect和WeakMap是ES6中引入的三个新的JavaScript特性。
Proxy对象用于定义基本操作的自定义行为(例如属性查找、赋值、枚举、函数调用等)。
const handler = {
get(target, prop, receiver) {
console.log(`GET ${prop}`);
return Reflect.get(target, prop, receiver);
},
set(target, prop, value, receiver) {
console.log(`SET ${prop} = ${value}`);
return Reflect.set(target, prop, value, receiver);
}
};
const target = { foo: 'bar' };
const proxy = new Proxy(target, handler);
proxy.foo; // 控制台输出: GET foo
proxy.foo = 'baz'; // 控制台输出: SET foo = baz
在上面的例子中,handler
对象定义了get
和set
陷阱,这些陷阱会在对应的操作发生时被调用。Proxy
对象proxy
拦截了对target
对象的属性访问和赋值操作,并打印出相应的信息。
Reflect
是一个内置的对象,它提供拦截JavaScript操作的方法。这些方法与Proxy
对象的陷阱方法相同。Reflect
不是一个函数对象,因此它是不可构造的。
const obj = {
foo: 1,
bar: 2,
get baz() {
return this.foo + this.bar;
}
};
console.log(Reflect.get(obj, 'foo')); // 1
console.log(Reflect.set(obj, 'foo', 3)); // true
console.log(obj.foo); // 3
在上面的例子中,Reflect.get()
和Reflect.set()
被用来获取和设置obj
对象的属性。
WeakMap
是一种特殊的Map,只接受对象作为键名(null
除外),并且键名所指向的对象不计入垃圾回收机制。
const weakMap = new WeakMap();
const obj1 = {};
const obj2 = {};
weakMap.set(obj1, 'hello');
weakMap.set(obj2, 'world');
console.log(weakMap.get(obj1)); // 'hello'
console.log(weakMap.get(obj2)); // 'world'
// 当obj1和obj2被清除后,weakMap中的条目也会自动被清除
obj1 = null;
obj2 = null;
在上面的例子中,weakMap
是一个WeakMap
实例,它使用了obj1
和obj2
作为键名。当obj1
和obj2
被设置为null
后,它们可以被垃圾回收器回收,weakMap
中对应的条目也会被自动清除。
这三个特性结合起来,可以用于实现私有变量、函数柯里化、数据绑定等高级功能。例如,结合Proxy
和WeakMap
可以实现一个简单的私有属性存储方案:
const privateData = new WeakMap();
class Person {
constructor(name, age) {
privateData.set(this, { name, age });
}
get name() {
return privateData.get(this).name;
}
get age() {
return privateData.get(this).age;
}
}
const person = new Person('Alice', 25);
console.log(person.name); // 'Alice'
console.log(person.age); // 25
在这个例子中,privateData
是一个WeakMap
,用于存储每个Person
实例的私有数据。由于WeakMap
的键名是弱引用,所以当Person
实例被垃圾回收时,对应的私有数据也会被自动清除。