Использовать прокси ES6 для перехвата Object.hasOwnProperty

Я хочу использовать прокси ES6, чтобы перехватить следующий общий код:

for (let key in trapped) {
    if (!Object.prototype.hasOwnProperty.call(obj, key)) continue;
    let value = trapped[key];
    //various code
}

Но после просмотра документации прокси я не уверен, как это сделать, главным образом потому, что has ловушка ловушка для in оператор, который, кажется, не используется в приведенном выше коде и нет ловушки для hasOwnProperty операция.

2 ответа

Решение

Вы можете использовать getOwnPropertyDescriptor обработчик для захвата hasOwnProperty() звонки.

Пример:

const p = new Proxy({}, {
  getOwnPropertyDescriptor(target, property) {
    if (property === 'a') {
      return {configurable: true, enumerable: true};
    }
  }
});

const hasOwn = Object.prototype.hasOwnProperty;

console.log(hasOwn.call(p, 'a'));
console.log(hasOwn.call(p, 'b'));

Это заданное поведение, а не особенность конкретной реализации:

  • Object.prototype.hasOwnProperty называет реферат [[HasOwnProperty]] операция
  • [[HasOwnProperty]] называет реферат [[GetOwnProperty]] операция
  • [[GetOwnProperty]] это что getOwnPropertyDescriptor ручки

На самом деле я собирался ответить на свой вопрос сам, но я был слишком медленным, и другие сначала ответили на него (кроме того, добавили очень полезную информацию). Тем не менее, вот ответ, который я хотел написать, на случай, если он может кому-то как-то помочь:


Похоже, что getOwnPropertyDescriptor ловушка срабатывает, когда hasOwnProperty называется. Таким образом, вы можете поймать в ловушку hasOwnProperty сделав следующее:

getOwnPropertyDescriptor(target, name) {
    return {
        value : target[name],
        //use a logical set of descriptors:
        enumerable : true,
        configurable : true,
        writable : true
    };
}

Другая часть ловушки get а также ownKeys также:

get(target, name) {
    return {}; //replace this with a relevant object
}

//These will be iterated over as part of the for loop
ownKeys() {
    return ["RelevantProperty1", "RelevantProperty2"];
}

В общем, поскольку вы должны возвращать массив свойств, когда вы перехватываете ownKeysиспользование прокси-сервера, кажется, не делает вещи намного лучше в этом случае использования. Я думаю, что для большинства ситуаций следующее будет работать так же хорошо и будет менее хрупким:

let obj = {};
let keys = ["a" , "b"];
for (let key of keys) {
    obj[key] = {}; //relevant object
}

Так что использование прокси может быть излишним.

Другие вопросы по тегам