Недавно я пытался изучить метапрограммирование на 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:
Я могу подтвердить, что это происходит и в Safari на iOS v11. Теперь это интересно.
FWIW, я обновил свой ответ подробностями о том, что происходит должен. Насколько я могу судить, Safari просто ошибается, не позволяя вам возвращать false для этого свойства.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


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