Reflect API — забытый герой ES2015

в 11:46, , рубрики: api, ES6, javascript

Везде и давно говорят о ES2015, хоть на дворе уже 2017 год, ещё есть люди не знакомые с этим стандартом. ES2015 принёс много нового в мир JavaScript, что-то подхватилось моментально, что-то продолжает оставаться в тени.

Все мы любим использовать модульный подход ES6, стрелочные функции, let и const, promises, классы, от деструктуризации многие пришли в восторг. Реже упоминается о новом типе Symbol, генераторах, Map, Set, WeakMap, WeakSet, и много чего ещё.

На мой взгляд основная причина обильного использования одних нововведений, и крайне редкое использование других — это практическая необходимость. Я не могу вспомнить случая, когда мне бы пригодилось использовать Map вместо обычных массивов или объектов. Генераторы я нахожу полезными и классно что в JS их добавили, но опять же, в моей практике написания Front-End'а, я если и находил им применение, то не чаще чем пару раз. Быть может я просто не изменил мышление и использую старые подходы к разработке под маской let, const, arrow function, классов, но поговорить я хочу всё же не об этом.

Несмотря на все эти WeakSet, генераторы и Symbol'ы, на мой взгляд наиболее всех в стороне оказались Reflect API и Proxy объекты. Давайте вспомним о них, а вдруг там есть что-то полезное.

Начнём с того что Reflect это не конструктор. Это как понятно из названия набор методов для работы с объектами подобно объекту Math.

Предлагаю освежить память и кратко пройтись по некоторым методам Reflect API:

  • Reflect.apply(target, this, args)

    Здесь всё понятно, метод для вызова функции с указанным контекстом. Принимает функцию, контекст, аргументы в виде массива.

    function countAmountScore(audienceScore, juryScore) {
       return this.userScore + audienceScore + juryScore;
    }
    let subZeroRating = Reflect.apply(countAmountScore, {userScore: 15}, [5, 10]); // выведет 30

  • Reflect.construct(constructor, args, prototype)

    С помощью этого метода можно вызвать конструктор без использования оператора new. Главной «плюшкой» использования этого метода на мой взгляд является третий, необязательный параметр. Это указание прототипа к обращаемой функции-конструктору.

    function checkFullName(name, surname) {
        this.name = name;
        this.surname = surname;
        this.getName = function() {
          return `${this.name} ${this.middleName} ${this.surname}`
        };
    }
    
    function addMiddleName () {}
    
    addMiddleName.prototype.middleName = 'Ильич';
    
    let Lenin = Reflect.construct(checkFullName, ['Владимир', 'Ленин'], addMiddleName);
    Lenin.getName(); // выведет "Владимир Ильич Ленин"

  • Reflect.defineProperty(object, property, attributes)

    Этот метод действует аналогично одноименному методу у Object, с той лишь разницей, что метод Reflect.defineProperty возвращает булевое значение, в зависимости от успеха или неудачи присвоения.

    Первым аргументом функции идёт объект к которому идёт присвоение свойства, вторым — имя свойства, третьим — опции или просто значение присваиваемого свойства.

  • Reflect.deleteProperty(target, property)

    Метод для удаления свойство и других сущностей, работает аналогично delete, с той лишь разницей, что возвращает булевое значение в зависимости от успеха или неудачи удаления.

  • Reflect.enumerate(object)

    Этот метод не рекомендуется использовать, т.к. он является «устаревшим» (obsolete), если верить документации, но в некоторых браузерах всё ещё может работать.

    Этот метод работает подобно for..in, но вместо того чтобы проходится по объекту — возвращает итерацию, проще говоря — генератор. Но так как многие интерпретаторы этот метод не понимают — рассматривать его нет смысла.

  • Reflect.get(object, property, this)

    Метод служит для получения свойства объекта, применим к массивам.

    // Object
    var obj = { x: 1, y: 2 };
    Reflect.get(obj, 'x'); // 1
    
    // Array
    Reflect.get(['zero', 'one'], 1); // "one"
    
    // Proxy with a get handler
    var x = {p: 1};
    var obj = new Proxy(x, {
      get(t, k, r) { return k + 'bar'; }
    });
    Reflect.get(obj, 'foo'); // "foobar"

  • Reflect.set(object, property, value, this)

    Работает аналогично методу Reflect.get с той лишь, что задаёт указанное значение, а не получает его.

    Метод Reflect.set возвращает булевое значение в зависимости от успеха или неудачи присвоения значения.

  • Reflect.has(object, property)

    Нужен для проверки существования свойства в объекте. Возвращает булевое значение.

    let building = {
        __proto__: {
            type: "castle"
        },
        age: 300
    };
    console.log(Reflect.has(building, "age"));  // выведет true
    console.log(Reflect.has(building, "type"));  // выведет true

  • Reflect.ownKeys(object)

    Метод Reflect.ownKeys — возвращает ключи элементов объекта, в виде массива. Наследуемые свойства игнорируются.

    let obj = {
      name: "Иван Федорович Крузенштерн",
      rank: "Адмирал",
      __proto__: {
        yearOfBirth: 1770
      }
    }
    
    let objKeys = Reflect.ownKeys(obj);
    console.log(objKeys.length);  // выведет 2
    console.log(objKeys[0]);  // выведет name
    console.log(objKeys[1]);  // выведет rank
    

В статье были приведены не все методы из Reflect.API, остальные показались мне почти целиком аналогичными одноименным методам собрата Object.

Положительный герой или отрицательный этот Reflect.API, есть ли в нём что-то полезное — каждый определит сам. Определённо этот программный интерфейс имеет право на жизнь.

Автор: CodeViking

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js