(obj, prop)
| 310 | function createProxy(target: any, path: string): any { |
| 311 | return new Proxy(target, { |
| 312 | get(obj, prop) { |
| 313 | const fullPath = path ? `${path}.${String(prop)}` : String(prop) |
| 314 | const value = obj[prop] |
| 315 | |
| 316 | // 记录访问日志 |
| 317 | if (typeof value === 'function') { |
| 318 | accessLog.push(`[调用函数] ${fullPath}()`) |
| 319 | } else { |
| 320 | accessLog.push(`[访问属性] ${fullPath}`) |
| 321 | } |
| 322 | |
| 323 | // 如果是函数,返回代理包装的函数 |
| 324 | if (typeof value === 'function') { |
| 325 | return new Proxy(value, { |
| 326 | apply(target, thisArg, args) { |
| 327 | accessLog.push( |
| 328 | `[执行函数] ${fullPath}(${args.map((a) => JSON.stringify(a).slice(0, 50)).join(', ')})` |
| 329 | ) |
| 330 | return Reflect.apply(target, thisArg, args) |
| 331 | } |
| 332 | }) |
| 333 | } |
| 334 | |
| 335 | // 如果是对象(但不是内置对象),递归代理 |
| 336 | if (value && typeof value === 'object' && !Array.isArray(value)) { |
| 337 | // 排除内置对象(Date、Math、RegExp 等) |
| 338 | if ( |
| 339 | value.constructor && |
| 340 | ['Date', 'Math', 'RegExp', 'String', 'Number', 'Boolean'].includes( |
| 341 | value.constructor.name |
| 342 | ) |
| 343 | ) { |
| 344 | return value |
| 345 | } |
| 346 | return createProxy(value, fullPath) |
| 347 | } |
| 348 | |
| 349 | return value |
| 350 | }, |
| 351 | set(obj, prop, value) { |
| 352 | const fullPath = path ? `${path}.${String(prop)}` : String(prop) |
| 353 | accessLog.push(`[设置属性] ${fullPath} = ${JSON.stringify(value).slice(0, 100)}`) |
nothing calls this directly
no test coverage detected