В документации ловушки Proxy ownKeys на MDN указано, что она будет перехватывать Object.keys()
вызовы:
Эта ловушка может перехватывать следующие операции:
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Объект.keys()
Reflect.ownKeys()
Однако, судя по моим тестам, это не работает с Object.keys
:
const proxy = new Proxy({}, {
ownKeys() {
console.info("called")
return ["a", "b", "c"]
}
})
console.info(Object.keys(proxy))
console.info(Object.getOwnPropertyNames(proxy))
console.info(Reflect.ownKeys(proxy))
Причина проста: Object.keys
возвращает только свойства с перечисляемым флагом. Чтобы проверить это, он вызывает внутренний метод [[GetOwnProperty]]
для каждого свойства, чтобы получить его дескриптор. А здесь, поскольку свойства нет, его дескриптор пустой, флаг перечисления отсутствует, поэтому оно пропущено.
Чтобы Object.keys
возвращал свойство, нам нужно, чтобы оно либо существовало в объекте с флагом enumerable, либо мы можем перехватывать вызовы [[GetOwnProperty]] (это делает ловушка getOwnPropertyDescriptor) и возвращать дескриптор с enumerable: true.
Вот пример:
let user = { };
user = new Proxy(user, {
ownKeys(target) { // called once to get a list of properties
return ['a', 'b', 'c'];
},
getOwnPropertyDescriptor(target, prop) { // called for every property
return {
enumerable: true,
configurable: true
/* ...other flags, probable "value:..." */
};
}
});
console.info( Object.keys(user) ); // ['a', 'b', 'c']
Object.keys
возвращает только перечисляемые собственные свойства объекта. У вашего прокси их нет, или, по крайней мере, он не сообщает о них в своей ловушке getOwnPropertyDescriptor
. Он работает с
const proxy = new Proxy({}, {
ownKeys() {
console.info("called ownKeys")
return ["a", "b", "c"]
},
getOwnPropertyDescriptor(target, prop) {
console.info(`called getOwnPropertyDescriptor(${prop})`);
return { configurable: true, enumerable: true };
}
})
console.info(Object.keys(proxy))
console.info(Object.getOwnPropertyNames(proxy))
console.info(Reflect.ownKeys(proxy))
const proxy = new Proxy({}, {
ownKeys: function () {
console.info("called")
return ["a", "b", "c"]
}
});
мой друг, я тестирую код, и он работает нормально. что я должен сделать, чтобы улучшить ответ
Хотя ответ, содержащий только код, может быть правильным, он помогает человеку, задавшему вопрос, но не приносит пользы ни ему, ни будущим посетителям. Пожалуйста, рассмотрите возможность улучшения вашего ответа.