Прокси серии ES6

JavaScript

Эта статья одновременно публикуется в личном блоге Github:Прокси серии ES6

предисловие

Несколько дней назад я смоделировал и реализовал две функции MobX —Рукописная реализация наблюдаемых и автозапускаемых методов MobX., который использует Proxy, поэтому я планирую узнать больше о Proxy и сделать заметку.

В том числе предыдущие серии ES6, плюс эта статья должна быть почти серией.

Что такое прокси

Proxy对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。 Можно понять, что уровень «перехвата» устанавливается перед целевым объектом, и внешний доступ к объекту должен сначала пройти этот уровень перехвата, поэтому предусмотрен механизм фильтрации и перезаписи внешнего доступа.

const p = new Proxy(target, handler)

Proxy(target, handler)target

Почему прокси

Прежде чем чему-то научиться, нужно подумать, зачем нам это нужно, на мой взгляд, вообще бывает несколько ситуаций.

  1. Проксируемый объект не хочет напрямую обращаться
  2. Управляет и изменяет поведение прикрепленного объекта (вызывающие свойства, назначения имущества, вызовы методов и т. Д.), Включение контроля доступа и повышенной функциональности.

API

Обзор API выглядит следующим образом:

  • get(target, propKey, receiver): перехватывает чтение свойств объекта, таких как proxy.foo и proxy['foo'] .
  • set(target, propKey, value, receiver): перехватывает настройку свойств объекта, таких как proxy.foo = v или proxy['foo'] = v , возвращает логическое значение.
  • has(target, propKey): перехватить операцию propKey в прокси и вернуть логическое значение.
  • deleteProperty(target, propKey): перехватить операцию удаления proxy[propKey] и вернуть логическое значение.
  • ownKeys(target): Перехват Object.getOwnPropertyNames (прокси), Object.getOwnPropertySymbols (прокси), Object.keys (прокси), for... в цикле возвращает массив. Этот метод возвращает все атрибуты имени самого целевого объекта, а Object.keys() возвращает результат, включающий только сам целевой объект, который может проходить по свойствам.
  • getOwnPropertyDescriptor(target, propKey): перехватить Object.getOwnPropertyDescriptor(proxy, propKey) и вернуть объект описания свойства.
  • defineProperty(target, propKey, propDesc): Перехват Object.defineProperty(proxy, propKey, propDesc),
  • Object.defineProperties(proxy, propDescs), который возвращает логическое значение.
  • preventExtensions(target): перехватить Object.preventExtensions(proxy) и вернуть логическое значение.
  • getPrototypeOf(target): перехватывать Object.getPrototypeOf(proxy) и возвращать объект.
  • isExtensible(target): Interception Object.isExtensible (прокси), возвращает логическое значение.
  • setPrototypeOf(target, proto): Obsock.SetPrototepeePeePOF (Proxy, Proto), возвращает логическое значение. Если целевой объект является функцией, то могут быть перехвачены две дополнительные операции.
  • apply(target, object, args)
  • construct(target, args)

Наиболее распространенный методgetа такжеset

пример

get

const target = {
  name: 'jacky',
  sex: 'man',
}
const handler = {
  get(target, key) {
    console.log('获取名字/性别')
    return Reflect.get(target, key)
  },
}
const proxy = new Proxy(target, handler)
console.log(proxy.name)

Запустить, принтные выходные устройства:

获取名字/性别
jacky

namegetметод, вgetметод печатает获取名字/性别, то черезReflect.get(target, key)Возвращаемое значение получает значение свойства, которое эквивалентноtarget[key]

set

const target = {
  name: 'jacky',
  sex: 'man',
}
const handler = {
  get(target, key) {
    console.log('获取名字/性别')
    return Reflect.get(target, key)
  },
  set(target, key, value) {
    return Reflect.set(target, key, `强行设置为 ${value}`)
  },
}
const proxy = new Proxy(target, handler)
proxy.name = 'monkey'
console.log(proxy.name)

Рабочий вывод:

获取名字/性别
强行设置 monkey

настраиватьproxy.name = 'monkey', который должен изменить значение свойства, он вызоветsetМетод, затем значение мы пытаемся изменить настройки обратно для достижения цели перехвата свойств объекта.


Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。
Reflect.get(target, name, receiver) :查找并返回target对象的name属性,如果没有该属性,则返回undefined。
Reflect.set(target, name, value, receiver) :设置target对象的name属性等于value。

это указывает на

Прокси-сервер изменит this в цели, чтобы указать на, как только прокси-сервер цели, this внутри цели будет указывать на прокси-прокси

const target = new Date('2021-01-03')
const handler = {}
const proxy = new Proxy(target, handler)

console.log(proxy.getDate())

Запустите код, найдете ошибку, подскажитеTypeError: this is not a Date object., то есть это не экземпляр объекта Date, и нам нужно вручную привязать исходный объект для его решения:

const target = new Date('2021-01-03')
const handler = {
  get(target, prop) {
    if (prop === 'getDate') {
      return target.getDate.bind(target) // 绑定
    }
    return Reflect.get(target, prop)
  },
}
const proxy = new Proxy(target, handler)

console.log(proxy.getDate()) // 3

Сценарии применения

  • Предупреждать или блокировать определенные действия
  • Проверка данных.判断数据是否满足条件

так далее...

Ссылаться на


пс:

Если вы считаете, что это хорошо, дайте мне звезду и дайте мне мотивацию продолжать творить!