Reflect, Proxy, Weak*

Reflect API

Отдельный модуль, содержащий различные методы, которые раньше были в Object, но их решили вынести в отдельный модуль. Плюс добавили пару новых плюшек

Зачем?

  • Модульность
  • Многие вещи пересекаются с Proxy, который является частью Reflect API

Методы из Object

  • getOwnPropertyDescriptor(target, name)
  • defineProperty(target, name, desc)
  • getOwnPropertyNames(target)
  • getPrototypeOf(target)
  • deleteProperty(target,name) 
  • freeze(target)
  • seal(target)
  • preventExtensions(target)
  • isFrozen(target)
  • isSealed(target)
  • isExtensible(target)
  • has(target,name)
  • hasOwn(target,name)
  • keys(target)

Несколько относительно новых вещей

  • get(target,name,receiver) - аналог target[name]
  • set(target,name,value,receiver) - аналог target[name] = value
  • apply(target,thisArg,args) - аналог Function.prototype.apply.call(fun,thisArg,args)
  • construct(target,args) - аналог new target(...args)

Proxy

Возможность переопределить поведение существующих объектов

Простой пример

var p = new Proxy(target, handler);

handler

  • getOwnPropertyDescriptor
  • ownKeys 
  • defineProperty
  • deleteProperty
  • preventExtensions
  • has 
  • get 
  • set
  • apply
  • construct

Пример кода

var handler = {
    get: function(target, name){
        return name in target?
            target[name] :
            37;
    }
};

var p = new Proxy({}, handler);
p.a = 1;
p.b = undefined;

console.log(p.a, p.b); // 1, undefined
console.log('c' in p, p.c); // false, 37

Валидация

let validator = {
  set: function(obj, prop, value) {
    if (prop === 'age') {
      if (!Number.isInteger(value)) {
        throw new TypeError('The age is not an integer');
      }
      if (value > 200) {
        throw new RangeError('The age seems invalid');
      }
    }

    // The default behavior to store the value
    obj[prop] = value;
  }
};

let person = new Proxy({}, validator);

person.age = 100;
console.log(person.age); // 100
person.age = 'young'; // Throws an exception
person.age = 300; // Throws an exception

Логирование

function makeLogger(obj) {
    return Proxy.create({
        get: function (target, name) {
            console.log('get', name, obj);
            return obj[name];
        },
        set: function (target, nave, val) {
            console.log('set', name, obj, value);
            obj[name] = val;
            return true;
        }
    }, Object.getPrototypeOf(obj));
}

WeakMap, WeakSet

Пример кода

var map = new WeakMap(),
    element = document.querySelector(".element");

map.set(element, "Original");

// later
var value = map.get(element);
console.log(value);             // "Original"

// later still - remove reference
element.parentNode.removeChild(element);
element = null;

value = map.get(element);
console.log(value);             // undefined

Reflect, Proxy, Weak*

By Pavel Trehubau

Reflect, Proxy, Weak*

  • 370