JS对象存属性值与存方法的差异、调用栈及最佳实践问题
问题1解答
你定义TokenProperties对象时,access_token对应的属性值会在脚本初始化阶段立即执行求值,也就是在所有业务函数运行前,就已经把当时PropertiesService里存的旧token读取出来,作为静态值存到了TokenProperties.access_token属性里。
后续你在checkToken里调用setProperty更新的是PropertiesService的存储值,不会触发已经初始化完成的对象属性重新赋值,所以读取到的一直是初始化时的旧值。
问题2解答
二者的核心差异是求值时机和结果时效性:
- 直接读取对象属性:求值发生在对象初始化阶段,结果是静态的原始值拷贝,只要没有主动重新赋值,值就不会变化,和后续存储层的更新完全隔离。
- 调用对象挂载的函数取值:求值发生在每次函数被调用的时刻,每次调用都会重新执行函数内的逻辑,从存储层读取最新的数值,拿到的永远是当前最新的结果。
问题3解答
两种写法的调用栈执行顺序如下:
- 脚本初始化阶段:首先执行
TokenProperties对象的初始化逻辑- 静态属性写法:此时就完成了
getProperty的调用,旧token存入access_token属性 - 函数写法:此时只是把函数定义赋值给
access_token属性,不会执行getProperty逻辑
- 静态属性写法:此时就完成了
- 业务逻辑触发
restCall函数执行 - 首先执行
checkToken:检测到token过期,调用getAccessToken getAccessToken请求新token,调用setProperty更新PropertiesService中的token值,执行完成后回到restCall上下文- 构造请求头阶段:
- 静态属性写法:直接读取初始化时缓存的旧值,拿到过期token
- 函数写法:实时调用
access_token(),执行getProperty读取最新存储的token,拿到有效值
问题4解答
你当前使用函数取值的用法是合理的,属于实现实时读取存储值的常规方案。
对应场景的最佳实践可以根据业务复杂度选择:
- 简单场景(token刷新频率低、调用量小):直接保留当前的函数取值写法,逻辑简单不易出错。
- 复杂场景(调用量高、需要减少存储读取次数):可以封装带缓存校验的token管理工具,把token值、过期时间存在内存中,每次取值先判断缓存是否有效,无效再去读取存储/刷新token,兼顾性能和正确性。
- 工程化场景:把token的获取、校验、刷新逻辑全部封装在独立模块中,不对外暴露存储操作,只暴露统一的
getValidToken()方法,避免业务代码直接操作token相关属性,减少出错概率。
内容的提问来源于stack exchange,提问作者Andy Fazulus
相关产品推荐
相关产品推荐

