Комментарии 18
Reflection/Reflect API — это API, который предоставляет возможность проводить реверс-инжиниринг классов, интерфейсов, функций, методов и модулей.
Ну конечно, это реверс-инженеринг, пора расходится.
Нужно посоветовать спрашивать определение термина реверс-инженеринг на собеседовании.
var foo = Object.freeze({bar: 1});
delete foo.bar;
Давно delete начал ошибку выбрасывать?
А так будет еще слегка короче, да и запись клевее смотрится))
Function.prototype.apply
// =>
Reflect.apply
// =>
(_=>_).apply
(_=>_).apply
Я бы тогда предложил:
((o)=>(o)).apply
Согласен что выглядит красиво. Но… ;)
lineLengths.reduce(_+_)
Reflect.apply
появился ведь не «потому что это логично, чтобы функция была в Reflect», а потому-что apply есть у всех конструкторов. То есть путь даже может быть такой:Function.prototype.apply
// =>
Function.apply
// =>
Reflect.apply
// =>
Number.apply
// =>
Array.apply
// =>
Date.apply
// =>
Map.apply
Из этих всех найболее сбалансированной по логичности/краткости мне кажется именно "
Function.apply
"Я понимаю, что сказанное ниже это вкусовщина (просто устал это видель в open-source проектах), но вы действительно считаете, что это:
const emptyObj = () =>
new Proxy({},
{
get: (target, key, receiver) => (
key == 'toJSON'
? () => target
: (
Reflect.has(target, key) ||
Reflect.set(target, key, emptyObj()),
Reflect.get(target, key, receiver)
)
)
}
)
;
понятнее, чем это:
const emptyObj = () => (
new Proxy({}, {
get(target, key, receiver) {
if (key === 'toJSON') {
return () => target;
}
if (!Reflect.has(target, key)) {
Reflect.set(target, key, emptyObj());
}
return Reflect.get(target, key, receiver);
}
})
);
У вас 15 строчек, и у меня 15 строчек, но ИМХО, в if'ах нет ничено плохого, используйте логические операторы по их назначению.
Визуально отделить эту запятую весьма непросто:
Reflect.has(target, key) ||
Reflect.set(target, key, emptyObj()), // <==
Reflect.get(target, key, receiver)
Это позволяет обрабатывать ошибки через условия, а не try-catch.
Это следует трактовать как дополнительную возможность или обработка ошибок через условие имеет какие-то явные преимущества? Просто интересуюсь. :)
Ну и отлов ошибок через try catch более громоздкий
Исторически мы привыкли, что блоки try catch проседают по перфомансу. Поэтому многие их избегают.
Это утверждение верно только для v8 ниже 5.8 (январь 2017, если не изменяет память) / Node.js v8.x.x. Да, конечно, не у всех еще обновлен хром / node до этих версий, тем не менее проблема решена, и ее доля в будущем будет только уменьшаться.
Ну и да, так как Reflect API появился достаточно недавно, придется использовать поллифил, а там try / catch.
Ну и отлов ошибок через try catch более громоздкий
Зато он понятнее в разы, предположим, что я определяю в дескрипторе сразу несколько свойств, и происходит ошибка (TypeError: Cannot define property xxx, object is not extensible
), в случае ошибки, можно понять, что именно произошло, а вот false
мне мало о чем скажет.
Почему вместо
(
Reflect.has(target, key) ||
Reflect.set(target, key, emptyObj()),
Reflect.get(target, key, receiver)
)
нельзя или плохо просто вот так:
{
if(!(key in target)){
target[key] = emptyObj();
}
return target[key];
}
Я далек от современного жс. Скажите, пожалуйста, почему в этом примере нельзя без Reflect?
const $ = selector =>
new Proxy(
document.querySelector(selector)||Element,
{ get: (target, key) => target[key] }
)
;
// Или даже без Proxy:
const $ = selector => document.querySelector(selector)||Element
Object.getPrototypeOf(1); // undefined
Не поверил. Проверил.
Хром 49: Number
Лис 52.2: Number
Опера 12.18: Unhandled Error: Object.getPrototypeOf: first argument not an Object
В каком undefined выдаёт?
Про Reflect API доступным языком