Pull to refresh

Comments 18

Определение нужно было оставить на конец, а то после него уже не интересно читать.

Reflection/Reflect API  —  это API, который предоставляет возможность проводить реверс-инжиниринг классов, интерфейсов, функций, методов и модулей.


Ну конечно, это реверс-инженеринг, пора расходится.

Нужно посоветовать спрашивать определение термина реверс-инженеринг на собеседовании.
   var foo = Object.freeze({bar: 1});
   delete foo.bar;

Давно delete начал ошибку выбрасывать?

function test(){
    'use strict'; // куда без него?

    let foo = Object.freeze({bar: 1});

    delete foo.bar;
}

test(); // Uncaught TypeError: Cannot delete property 'bar' of #<Object>
Некоторые записи выходят короче

А так будет еще слегка короче, да и запись клевее смотрится))
Function.prototype.apply
// =>
Reflect.apply
// =>
(_=>_).apply
(_=>_).apply


Я бы тогда предложил:
((o)=>(o)).apply


Согласен что выглядит красиво. Но… ;)
вот и настал век программирования на смайликах...
Прям как рисование поп в Scala,
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 более громоздкий
Исторически мы привыкли, что блоки try catch проседают по перфомансу. Поэтому многие их избегают.

Это утверждение верно только для v8 ниже 5.8 (январь 2017, если не изменяет память) / Node.js v8.x.x. Да, конечно, не у всех еще обновлен хром / node до этих версий, тем не менее проблема решена, и ее доля в будущем будет только уменьшаться.


Ну и да, так как Reflect API появился достаточно недавно, придется использовать поллифил, а там try / catch.


Benchmarks

image


Ну и отлов ошибок через try catch более громоздкий

Зато он понятнее в разы, предположим, что я определяю в дескрипторе сразу несколько свойств, и происходит ошибка (TypeError: Cannot define property xxx, object is not extensible), в случае ошибки, можно понять, что именно произошло, а вот false мне мало о чем скажет.

Я тут не ухватываю чего-то главного, из-за чего назначение Reflect остаётся загадкой.
Почему вместо
(
    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
С прокси больше возможностей по перехвату. Сделать без прокси и рефлекта — пожалуйста. И да, это простые примеры. Так же как для примеров в ФП показывают частное применние на примере функций add()() где не виден смысл. Более сложные примеры сложнее объяснять. Никто не мешает написать 10 строк кода с if'ами и try-catch'ами. Все так же будет работать. Наверное с jQ не самый удачный пример оказался.
Object.getPrototypeOf(1); // undefined

Не поверил. Проверил.
Хром 49: Number
Лис 52.2: Number
Опера 12.18: Unhandled Error: Object.getPrototypeOf: first argument not an Object
В каком undefined выдаёт?
Sign up to leave a comment.