Skip to content

Instantly share code, notes, and snippets.

@monochromer
Created June 19, 2019 14:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save monochromer/fd05225ce1844925dcf3e394a6816ea4 to your computer and use it in GitHub Desktop.
Save monochromer/fd05225ce1844925dcf3e394a6816ea4 to your computer and use it in GitHub Desktop.
A practical guide to Javascript Proxy (ES6 Proxy)

Thomas Barrasso A practical guide to Javascript Proxy (ES6 Proxy) https://blog.bitsrc.io/a-practical-guide-to-es6-proxy-229079c3c2f0

Gergo Bogdan https://github.com/gergob/jsProxy

  1. Default / "Zero Values"
const withZeroValue = (target, zeroValue) => new Proxy(target, {
  get: (obj, prop) => (prop in obj) ? obj[prop] : zeroValue
})
  1. Negative Array Indices
arr[-1], arr[arr.length - 1]
const negativeArray = (items) => new Proxy(items, {
  get: (target, propKey, receiver) => Reflect.get(target,
    (+propKey < 0) ? String(target.length + +propKey) : propKey, receiver)
});
  1. Hiding Properties (private _-props )
const hide = (target, prefix = '_') => new Proxy(target, {
  has: (obj, prop) => (!prop.startsWith(prefix) && prop in obj),
  ownKeys: (obj) => Reflect.ownKeys(obj)
    .filter(prop => (typeof prop !== "string" || !prop.startsWith(prefix))),
  get: (obj, prop, rec) => (prop in rec) ? obj[prop] : undefined
})
  1. Caching
const ephemeral = (target, ttl = 60) => {
  const CREATED_AT = Date.now()
  const isExpired = () => (Date.now() - CREATED_AT) > (ttl * 1000)
  
  return new Proxy(target, {
    get: (obj, prop) => isExpired() ? undefined : Reflect.get(obj, prop)
  })
}
  1. Enums & Read-Only Views
const NOPE = () => {
  throw new Error("Can't modify read-only view");
}

const NOPE_HANDLER = {
  set: NOPE,
  defineProperty: NOPE,
  deleteProperty: NOPE,
  preventExtensions: NOPE,
  setPrototypeOf: NOPE
}

const readOnlyView = target =>
  new Proxy(target, NOPE_HANDLER)


const createEnum = (target) => readOnlyView(new Proxy(target, {
  get: (obj, prop) => {
    if (prop in obj) {
      return Reflect.get(obj, prop)
    }
    throw new ReferenceError(`Unknown prop "${prop}"`)
  }
}))


let SHIRT_SIZES = createEnum({
  S: 10,
  M: 15,
  L: 20
})

SHIRT_SIZES.S // 10
SHIRT_SIZES.S = 15

// Uncaught Error: Can't modify read-only view

SHIRT_SIZES.XL

// Uncaught ReferenceError: Unknown prop "XL"
  1. Operator Overload
const range = (min, max) => new Proxy(Object.create(null), {
  has: (_, prop) => (+prop >= min && +prop <= max)
})

if (X in range(1, 100)) { // true
  // ...
}
  1. Cookies Object
const getCookieObject = () => {
  const cookies = document.cookie
  .split(';')
  .reduce((cks, ck) => ({
    [ck.substr(0, ck.indexOf('=')).trim()]: ck.substr(ck.indexOf('=') + 1),
    ...cks
  }), {});
  const setCookie = (name, val) => document.cookie = `${name}=${val}`;
  const deleteCookie = (name) => document.cookie = `${name}=; expires=Thu, 01 Jan 1970 00:00:01 GMT;`;

  return new Proxy(cookies, {
    set: (obj, prop, val) => (setCookie(prop, val), Reflect.set(obj, prop, val)),
    deleteProperty: (obj, prop) => (deleteCookie(prop), Reflect.deleteProperty(obj, prop))
   })
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment