Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

The Traps

Every fundamental object operation has a corresponding trap.

Reference Table

TrapInterceptsReflect Equivalent
getProperty readReflect:get
setProperty writeReflect:set
hasin operatorReflect:has
delete-propertydelete operatorReflect:delete-property
applyFunction callReflect:apply
constructnew operatorReflect:construct
own-keysObject:keys etc.Reflect:own-keys
get-own-property-descriptorDescriptor lookupReflect:get-own-property-descriptor
define-propertyObject:define-propertyReflect:define-property
get-prototype-ofObject:get-prototype-ofReflect:get-prototype-of
set-prototype-ofObject:set-prototype-ofReflect:set-prototype-of
is-extensibleObject:is-extensibleReflect:is-extensible
prevent-extensionsObject:prevent-extensionsReflect:prevent-extensions

get — The Most Common Trap

Default values for missing properties:

(bind handler (obj
  :get (fn (:any target :string prop :any receiver)
    (if (in prop target)
      (Reflect:get target prop receiver)
      (template "No property '" prop "'")))))

set — Validation on Write

(bind handler (obj
  :set (fn (:any target :string prop :any value :any receiver)
    (if (and (= prop "age") (or (not (= (typeof value) "number")) (< value 0)))
      (throw (new TypeError "age must be a non-negative number")))
    (Reflect:set target prop value receiver))))

apply — Intercept Function Calls

(func with-logging
  :args (:function f)
  :returns :any
  :body
  (new Proxy f (obj
    :apply (fn (:any target :any this-arg :any args)
      (console:log (template "Calling with " args))
      (Reflect:apply target this-arg args)))))

The Pattern

Every trap follows the same shape: do your custom logic, then call the corresponding Reflect method to perform the default operation. Reflect is the Proxy API’s companion — it provides exactly the default behaviour that each trap would perform if not intercepted.