One symbol that is widely recognized is Symbol.iterator
. When this symbol is defined as a generator function property on an object, it enables the object to be utilized in a [...object]
syntax. For example, you can do something like this:
const newArray = [ ...foo, ...object, ...bar ];
However, I have not been able to find a similar functionality that allows for this:
const newObject = { ...foo, ...object, ...etc };
or using Object.assign
with non-own properties. An example of this is seen in instances of ES6 classes with accessors like get prop() / set prop()
- they are defined on the .prototype
property of the class constructor:
const C = class {
#num = 42;
#str = 'aaa';
get num() { return this.#num; }
set num(val) { /* validate new value */ this.#num = val; return true; }
get str() { return this.#num; }
set str(val) { /* validate new value */ this.#num = val; return true; }
}
const obj = new C();
Now, obj
has validation for obj.num = ...
and obj.str = ...
. However, it cannot be used in {...foo, ...obj}
, or in Object.assign(foo, obj)
, due to the accessors being on the prototype. While Proxies can be spread and property access trapped for validation, my goal is to ensure that accessing obj.prop
closely matches the performance of accessing plain object properties. Consider the following:
const p = new Proxy({ num: 0 }, {});
suite.add('instance with class-accessors', () => obj.num++);
suite.add('proxy', () => p.num++);
suite.run();
instance with class-accessors x ***235***,971,841 ops/sec ±0.20% (86 runs sampled)
proxy x ***1***,014,238 ops/sec ±1.91% (84 runs sampled)
This shows a significant difference in speed! So, is there a way to allow { ...obj }
/ Object.assign
for instances with prototype-based getters?
I've experimented by defining *[Symbol.iterator]() {...}
in the class, yielding pairs in the style of Object.entries
, but it did not work. I checked MDN's "Well known symbols" and didn't find any useful solutions. I expected to find something like Symbol.entries
that could control the spread/assign behavior and make working with instances containing getters more transparent.