1

I want to add some metadata to an array, like a tag, but not actual data.

Say I have a symbol like:

const s = Symbol('foo')

Say I declare an array like so:

const v = [1,2,3];

is there a good way to tag the array with the symbol? Obviously adding it as a property might work:

v[s] = true;

I assume that this wont break anything and when the array is traversed the symbol property will never be hit? dunno!

Update: when I do this:

console.log(v);

I get:

[ 1, 2, 3, [Symbol(foo)]: true ]

but when I do:

v.forEach(x => console.log(x));

I just get:

1
2
3
  • It's fine. Normal iteration using `for...in`, `for...of`, and static `Object` methods specifically for string properties will not access the symbol property. However, what is the use-case for this? Note that `Symbol` is not very portable since transpiling to ES5 causes significant runtime overhead in order to polyfill properly. The reason I bring this up is that there's probably a better way to do what you're trying to do. – Patrick Roberts Nov 16 '18 at 21:57
  • 2
    Also be aware that symbol properties are [not hidden](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/getOwnPropertySymbols), and that they are not copied when doing `map`, `filter`, `concat`, ... – trincot Nov 16 '18 at 22:04
  • @PatrickRoberts adding metadata as fields, without adding data – Alexander Mills Nov 16 '18 at 22:24
  • @trincot I am having trouble determining what you mean by "not hidden", they seem to be hidden for all operations except when reading the property directly by having a reference to the symbol itself. – Alexander Mills Nov 16 '18 at 22:26
  • 1
    Did you visit the link? – trincot Nov 16 '18 at 22:40

1 Answers1

3

I assume that this wont break anything and when the array is traversed the symbol property will never be hit?

Yes, neither iteration nor enumeration (which you shouldn't do on arrays anyway) will hit the symbol. The only way to access the symbol is Object.getOwnPropertySymbols.

console.log is just trying to be helpful for debugging purposes. It's not something you would need to hide from.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • yeah I guess symbols are non-enumerable props by default - when you use console.log it will look for all props, including non-enumerable ones? –  Nov 16 '18 at 22:32
  • @rakim Symbols actually are ["enumerable"](https://stackoverflow.com/q/31029612/1048572), but they still don't get enumerated by `for … in` or `Object.keys` or `Object.getOwnPropertyNames` because those look for string-named properties only. – Bergi Nov 16 '18 at 22:35
  • @rakim And yes, `console.log` uses the debugger inspection view that exposes simply everything. Sometimes even things that are completely inaccessible to code, e.g. on closures or WeakMaps. – Bergi Nov 16 '18 at 22:36
  • @PatrickRoberts No, it certainly won't. `for (const symbol of Object.getOwnPropertySymbols(o))` already perfectly fills that niche. – Bergi Nov 17 '18 at 14:08
  • @Bergi that's like saying `for (const key of Object.keys(o))` is a suitable replacement for `for (const key in o)`. The point is lazy iteration, whereas `getOwnPropertySymbols()` returns an array instead of an iterator. – Patrick Roberts Nov 17 '18 at 18:30
  • @PatrickRoberts True, although doing it non-lazily is probably better for loop performance anyway. And I've never really needed a lazy iteration (iterating over properties that were added during the loop?) so I doubt the ES committee would add new syntax for this. – Bergi Nov 17 '18 at 18:42