不评估访问器,检测Object.defineProperty的链式数据描述符
链式数据描述符检测与无限递归问题拆解
咱们先把核心需求理清楚:我们不需要直接去评估访问器,而是要检测Object.defineProperty是否存在链式数据描述符——简单说就是某个属性的描述符里,它的value本身又关联了其他描述符的情况。
拿你提到的示例来说,我们要检测属性'cv'是否存在这种链式关联,但这里有个坑:如果处理的是纯数据描述符,很容易陷入无限递归——因为JS会一个劲返回同一个数据描述符,导致检测逻辑死循环。
那怎么识别链式结构深处的访问器呢?其实很简单:如果链式结构里某一层存在get或set访问器函数,我们直接检查这两个函数是否定义就能识别出来。
可行的解决思路
我们的核心目标是利用value属性的描述符,把原描述符的value属性复制出来存到某个地方,然后用一个自定义逻辑(比如访问器或者代理)来替代原有的链式结构——这样既能避开无限递归,又能正确捕获深层的访问器逻辑。具体可以这么走:
- 先拿到目标属性的描述符,判断它是数据描述符还是访问器描述符
- 如果是数据描述符,先把它的
value对应的描述信息存好 - 然后把原属性的描述符替换成自定义的访问器,在访问器内部处理原value的链式逻辑,同时避免递归调用
- 要是检测到深层有访问器,直接触发对应的
get/set逻辑就行
给你写个简化的代码示例辅助理解:
function handleChainedDescriptor(obj, prop) { let desc = Object.getOwnPropertyDescriptor(obj, prop); if (!desc) return; // 先判断是不是访问器描述符 if ('get' in desc || 'set' in desc) { console.log(`属性${prop}存在访问器`); return; } // 处理数据描述符的链式嵌套 if ('value' in desc) { // 先保存原value的完整描述符 const originalValueDesc = {...desc}; // 替换成自定义访问器,避免递归死循环 Object.defineProperty(obj, prop, { get() { // 这里可以检测原value对应的深层描述符 const innerDesc = Object.getOwnPropertyDescriptor(this, `_${prop}`); if (innerDesc && ('get' in innerDesc)) { return innerDesc.get.call(this); } return originalValueDesc.value; }, set(newVal) { originalValueDesc.value = newVal; }, configurable: desc.configurable, enumerable: desc.enumerable }); } }
提醒一下:上面是简化版的示例,实际用的时候得考虑更多边界情况,比如原属性的
configurable、enumerable属性的继承,还有多层链式嵌套的处理哦。
内容的提问来源于stack exchange,提问作者user2994430
相关产品推荐
相关产品推荐

