I'm implementing a native module for node and trying to return something that looks like an array but is backed by native data. At the moment I'm creating an ObjectTemplate and using SetIndexedPropertyHandler so I can handle attempts to get indexes from JS. This all works, but from JS this just looks like an Object, not an Array. Is there any way I can make this look more like an array?
How can I return something that looks like an array from a node addon?
69 views Asked by Dave Townsend AtThere are 3 answers
All arraylike objects must have length
. As long as they have that property, you can borrow Array
functions and run them on your object (e.g. Array.prototype.forEach.call(obj, ...)
), or in ES6 run Array.from
on it:
obj = {
0: "foo",
1: "bar",
length: 2
};
// ES5 way to get a real array:
console.log(Array.prototype.slice.call(obj));
// ES6 way to get a real array:
console.log(Array.from(obj));
If you actually want to return an array and not an arraylike object, then I suggest you use array = Array::New()
and array->Set(index, element)
instead of ObjectTemplate
. There's an example in this question.
You could consider using a Proxy around a real array, with traps/handlers that interface with your native object. There's a performance penalty to using proxies (don't try to iterate over a proxied array if it's an important, hot code path), but they let you do just about anything.
var _arr = [];
var arraylike = new Proxy(_arr, {
get: function (target, prop) {
// Interface with your native object here.
if (prop === "length") return 20;
return "hello";
}
});
// Consume
> arraylike.length
20
> arraylike[5]
"hello"
> arraylike instanceof Array
true
> Array.isArray(arraylike)
true
It's also perfectly valid to prototypically inherit from Array
in javascript.
You can return
Object.entries(object)
.