code: function get (target, key, receiver) {
    const result = Reflect.get(target, key, receiver)
    // do not register (observable.prop -> reaction) pairs for well known symbols
    // these symbols are frequently retrieved in low level JavaScript under the hood
    if (typeof key === 'symbol' && wellKnownSymbols.has(key)) {
      return result
    }
    // register and save (observable.prop -> runningReaction)
    registerRunningReactionForOperation({ target, key, receiver, type: 'get' })
    // if we are inside a reaction and observable.prop is an object wrap it in an observable too
    // this is needed to intercept property access on that object too (dynamic observable tree)
    const observableResult = rawToProxy.get(result)
    if (hasRunningReaction() && typeof result === 'object' && result !== null) {
      if (observableResult) {
        return observableResult
      }
      // do not violate the none-configurable none-writable prop get handler invariant
      // fall back to none reactive mode in this case, instead of letting the Proxy throw a TypeError
      const descriptor = Reflect.getOwnPropertyDescriptor(target, key)
      if (
        !descriptor ||
        !(descriptor.writable === false && descriptor.configurable === false)
      ) {
        return observable(result)
      }
    }
    // otherwise return the observable wrapper if it is already created and cached or the raw object
    return observableResult || result
  }
docs: intercept get operations on observables to know which reaction uses their properties