Skip to content

Commit 2b49b43

Browse files
mcollinatargos
authored andcommitted
doc: added symbols guidelines
PR-URL: #22684 Reviewed-By: Tobias Nießen <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Ruben Bridgewater <[email protected]> Reviewed-By: Luigi Pinca <[email protected]> Reviewed-By: Vse Mozhet Byt <[email protected]> Reviewed-By: Daniel Bevenius <[email protected]> Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Anatoli Papirovski <[email protected]>
1 parent 2cb01f0 commit 2b49b43

File tree

1 file changed

+73
-0
lines changed

1 file changed

+73
-0
lines changed

doc/guides/using-symbols.md

+73
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
# Using global symbols
2+
3+
ES6 introduced a new type: `Symbol`. This new type is _immutable_, and
4+
it is often used for metaprogramming purposes, as it can be used as
5+
property keys like string. There are two types of
6+
symbols, local and global.
7+
Symbol-keyed properties of an object are not included in the output of
8+
`JSON.stringify()`, but the `util.inspect()` function includes them by
9+
default.
10+
11+
Learn more about symbols at
12+
https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol.
13+
14+
## `Symbol(string)`
15+
16+
Symbols created via `Symbol(string)` are local to the caller function.
17+
Note that `Symbol('hello') !== Symbol('hello')`.
18+
For this reason, we often use them to simulate private fields, like so:
19+
20+
```js
21+
const kField = Symbol('kField');
22+
23+
console.log(kField === Symbol('kField')); // false
24+
25+
class MyObject {
26+
constructor() {
27+
this[kField] = 'something';
28+
}
29+
}
30+
31+
module.exports.MyObject = MyObject;
32+
```
33+
34+
Note that Symbols are not _fully private_, as the data could be accessed
35+
anyway:
36+
37+
```js
38+
for (const s of Object.getOwnPropertySymbols(obj)) {
39+
const desc = s.toString().replace(/Symbol\((.*)\)$/, '$1');
40+
if (desc === 'kField') {
41+
console.log(obj[s]); // 'something'
42+
}
43+
}
44+
```
45+
46+
Local symbols make it harder for developers to monkey patch/access
47+
private fields, as they require more work than a property prefixed
48+
with an `_`. Monkey patching private API that were not designed to be
49+
monkey-patchable make maintaining and evolving Node.js harder, as private
50+
properties are not documented and can change within a patch release.
51+
Some extremely popular modules in the ecosystem monkey patch some
52+
internals, making it impossible for us to update and improve those
53+
areas without causing issues for a significant amount of users.
54+
55+
## `Symbol.for`
56+
57+
Symbols created with `Symbol.for(string)` are global and unique to the
58+
same V8 Isolate. On the first call to `Symbol.for(string)` a symbol is
59+
stored in a global registry and easily retrieved for every call of
60+
`Symbol.for(string)`. However, this might cause problems when two module
61+
authors use the same symbol
62+
for different reasons.
63+
64+
```js
65+
const s = Symbol.for('hello');
66+
console.log(s === Symbol.for('hello'));
67+
```
68+
69+
In the Node.js runtime we prefix all our global symbols with `nodejs.`,
70+
e.g. `Symbol.for('nodejs.hello')`.
71+
72+
Global symbols should be preferred when a developer-facing interface is
73+
needed to allow behavior customization, i.e., metaprogramming.

0 commit comments

Comments
 (0)