I need to exercise some code in data mapping functions. For this, I need a proxy that returns an iterable array with one element (itself; an iterable array) when any property is requested. This will activate all loops and property checks in the data mapper layer (not shown here).
Something like this:
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
}}
)
This starts off well:
> p.any.length
1
but fails here:
> for(let v of p.any){console.log(v)}
Uncaught TypeError: p.any is not iterable
I need the loop to iterate and console.log one element:
> p.any
Proxy [
<ref *1> [ Proxy [ [Circular *1], [Object] ] ],
{ get: [Function: get] }
]
Some proxy docs and guides cover the in
and object but do not cover the of
and array.
2
Answers
Note: I am by no means a pro with the Proxy API, but hopefully, I can help you out at least a bit.
Could you do something like this?
Then when you run your loop:
You should see this:
The error occurs because the
for..of
loop will query the proxy object with the@@iterator
symbol property, and your code will react by returningp
, and not an iterator as is whatArray.prototype[Symbol.iterator]
returns.The solution is simple: just like you let the access to
length
andpush
let through, also do the same with symbol properties.Another thing you may consider is to not do
p.push(p)
, butobj.push(p)
. That way you can ignore apush
that is issued by the user, and can perform this action as the first action.Resulting code:
Maybe you should also let other property accesses pass through, like array methods (
forEach
,reduce
,map
,filter
,… etc).