Прокси-сервер не работает должным образом

Недавно я пытался изучить метапрограммирование на javaScript. Однако этот сценарий пишет

false
true

на консоль, когда я ожидал, что она дважды запишет true:

var foo = new Proxy({x:20,y:20},{
  has: function(target, prop) {
    console.info(target.hasOwnProperty(prop)) //false
    if (target.hasOwnProperty(prop)){
      return true; 
    }
    return false; //gets returned???
  }
});

console.info('toString' in foo) //true

Примечание: Люди ответили, что он показывает false дважды, и это как и ожидалось. Я получаю false, затем true, используя vanilla Safari, 10.1.2, без расширений, кроме отключенных Flash и Java:

Прокси-сервер не работает должным образом

Vanilla Safari, 10.1.2, без расширений, кроме отключенных Flash и Java. Я чувствовал, что это подразумевалось, что я каким-то образом занимался троллингом, поскольку получил два отрицательных голоса за то, что, по моему мнению, было совершенно законным вопросом.

Ben Rivers 07.04.2018 13:33

Я могу подтвердить, что это происходит и в Safari на iOS v11. Теперь это интересно.

T.J. Crowder 07.04.2018 13:38

FWIW, я обновил свой ответ подробностями о том, что происходит должен. Насколько я могу судить, Safari просто ошибается, не позволяя вам возвращать false для этого свойства.

T.J. Crowder 07.04.2018 14:12
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
3
152
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

я получил false дважды

var foo = new Proxy({x:20,y:20},{
  has: function(target, prop) {
    console.info(target.hasOwnProperty(prop)) 
    if (target.hasOwnProperty(prop)){
      return true; 
    }
    return false; 
  }
});
console.info('toString' in foo);
console.info('x' in foo)

Если вы запустите console.info('x' in foo), вы получите дважды true, потому что свойство x существует в {x:20,y:20}, а toString существует в Object.prototype.

И вот почему

let obj = {x:20,y:20};
console.info('x' in obj);//true
console.info('toString' in obj);//true
console.info(Object.getOwnPropertyNames(obj));//['x','y']
console.info(obj.hasOwnProperty('x'));//true
console.info(obj.hasOwnProperty('y'));//true
console.info(obj.hasOwnProperty('toString'));//false
Ответ принят как подходящий

Что ж, действительно очень интересно, что Safari показывает вам false, а затем true. (Я могу убедиться, что это тоже показывает мне в iOS Safari на iOS v11.2.6.) in использует абстрактную операцию HasProperty, которая использует внутреннюю операцию [[HasProperty]] объекта, на котором вы ее используете (в вашем случае , прокси). шаги для операции [[HasProperty]] для прокси-объектовделать позволяет результату отличаться от того, что ваш обработчик возвращает, если ваш обработчик возвращает false, но дополнительные проверки, которые могли бы сделать это, не применимы к вашему коду. В частности: обработчику has не разрешается говорить, что свойство не существует, если оно существует как «собственное» свойство на целевом объекте и либо 1) это свойство не настраивается, либо 2) объект не расширяется. У вашего целевого объекта нет собственного свойства toString, поэтому это не применимо. Так что похоже, что Safari может делать эти проверки немного неправильно. Если посмотреть на спецификации снимков ES2015, ES2016 и ES2017, это поведение не изменилось с момента появления прокси.

FWIW, он должен выводить false дважды, потому что:

  • target не имеет своего свойства собственный под названием toString (он наследует его от Object.prototype), поэтому console.info(target.hasOwnProperty(prop)); правильно показывает false.

  • Поскольку ваш прокси возвращает результат hasOwnProperty (несколько косвенно), console.info('toString' in foo); также правильно показывает false.

Если вы хотите, чтобы has выполнял нормальное поведение, лучший способ сделать это, вероятно, - использовать Reflect.has:

var foo = new Proxy({x:20,y:20},{
  has: function(target, prop) {
    var flag = Reflect.has(target, prop);
    console.info(flag); // true
    return flag;
  }
});

console.info('toString' in foo) // true

... или, конечно, вы можете использовать in:

var foo = new Proxy({x:20,y:20},{
  has: function(target, prop) {
    var flag = prop in target;
    console.info(flag); // true
    return flag;
  }
});

console.info('toString' in foo) // true

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