如何实现ES6 Proxy返回可迭代数组?解决for...of循环报错问题
解决ES6 Proxy数组无法被for...of迭代的问题
需求背景
需要实现一个ES6 Proxy,访问其任意属性时返回包含自身的可迭代数组,以此触发数据映射层的所有循环和属性检查。
原代码及问题
原实现代码:
p = new Proxy([], { get(obj, prop) { if(prop === 'length') return obj.length if(prop === 'push') return obj.push if(p.length === 0) p.push(p) return p }} )
初始属性访问测试正常:
> p.any.length 1
但执行for...of循环时抛出错误:
> for(let v of p.any){console.log(v)} Uncaught TypeError: p.any is not iterable
此时p.any的输出为:
Proxy [ <ref *1> [ Proxy [ [Circular *1], [Object] ] ], { get: [Function: get] } ]
问题原因
for...of循环的执行依赖于对象的Symbol.iterator方法——该方法会返回一个迭代器,循环通过迭代器遍历元素。原Proxy的get陷阱没有处理Symbol.iterator这个特殊属性,导致访问它时返回的是Proxy自身,而非数组的迭代器方法,因此无法触发正常迭代。
修复方案
在get陷阱中添加对Symbol.iterator的处理,返回目标数组的迭代器方法(注意绑定原数组的this上下文,避免迭代器失效):
p = new Proxy([], { get(obj, prop) { if(prop === 'length') return obj.length if(prop === 'push') return obj.push // 处理迭代器属性,返回原数组的迭代器方法 if(prop === Symbol.iterator) return obj[Symbol.iterator].bind(obj) if(p.length === 0) p.push(p) return p }} )
验证结果
修复后执行循环,会正常迭代并输出数组中的元素:
> for(let v of p.any){console.log(v)} Proxy [ [Circular *1], { get: [Function: get] } ]
内容的提问来源于stack exchange,提问作者jcalfee314
相关产品推荐
相关产品推荐

