ownKeys 陷阱函数
ownKeys 代理陷阱拦截了内部方法 ,并允许你返回一个数组用于重写该行为。返回的这个数组会被用于四个方法:Object.keys() 方法、 Object.getOwnPropertyNames() 方法、Object.getOwnPropertySymbols() 方法与 Object.assign() 方法,其中 Object.assign() 方法会使用该数组来决定哪些属性会被复制。
ownKeys 陷阱函数的默认行为由 Reflect.ownKeys() 方法实现,会返回一个由全部自有属性的键构成的数组,无论键的类型是字符串还是符号。Object.getOwnProperyNames() 方法与 Object.keys() 方法会将符号值从该数组中过滤出去;相反,Object.getOwnPropertySymbols() 会将字符串值过滤掉;而 Object.assign() 方法会使用数组中所有的字符串值与符号值。
ownKeys 陷阱函数接受单个参数,即目标对象,同时必须返回一个数组或者一个类数组对象,不合要求的返回值会导致错误。你可以使用 ownKeys 陷阱函数去过滤特定的属性,以避免这些属性被 Object.keys() 方法、Object.getOwnPropertyNames() 方法、Object.getOwnPropertySymbols() 方法或 Object.assign() 方法使用。假设你不想在结果中包含任何以下划线打头的属性(在 JS 的编码惯例中,这代表该字段是私有的),那么可以使用 ownKeys 陷阱函数来将它们过滤掉,就像下面这样:
let proxy = new Proxy({}, {
ownKeys(trapTarget) {
return Reflect.ownKeys(trapTarget).filter(key => {
return typeof key !== "string" || key[0] !== "_";
});
}
});
let nameSymbol = Symbol("name");
proxy.name = "proxy";
proxy._name = "private";
proxy[nameSymbol] = "symbol";
let names = Object.getOwnPropertyNames(proxy),
keys = Object.keys(proxy);
symbols = Object.getOwnPropertySymbols(proxy);
console.log(names.length); // 1
console.log(names[0]); // "name"
console.log(keys.length); // 1
console.log(keys[0]); // "name"
console.log(symbols.length); // 1
console.log(symbols[0]); // "Symbol(name)"
这个例子使用了一个 ownKeys 陷阱函数,首先调用了 Reflect.ownKeys() 方法来获取目标对象的键列表;接下来,filter() 方法被用于将所有下划线打头的字符串类型的键过滤出去;这之后向 proxy 对象添加了三个属性:name、_name 与 nameSymbol。当 proxy 对象上的 Object.getOwnPropertyNames() 方法与 Object.keys() 方法被调用时,只获得了 name 属性;类似的,Object.getOwnPropertySymbols() 方法被调用时只获得了 nameSymbol 属性;而 _name 属性则始终没有出现在结果里,因为它被过滤了。
ownKeys 陷阱函数也能影响 for-in 循环,因为这种循环调用了陷阱函数来决定哪些值能够被用在循环内。 |