summaryrefslogtreecommitdiff
path: root/doc/guides/using-symbols.md
diff options
context:
space:
mode:
Diffstat (limited to 'doc/guides/using-symbols.md')
-rw-r--r--doc/guides/using-symbols.md73
1 files changed, 73 insertions, 0 deletions
diff --git a/doc/guides/using-symbols.md b/doc/guides/using-symbols.md
new file mode 100644
index 0000000000..1e79e1a4e4
--- /dev/null
+++ b/doc/guides/using-symbols.md
@@ -0,0 +1,73 @@
+# Using global symbols
+
+ES6 introduced a new type: `Symbol`. This new type is _immutable_, and
+it is often used for metaprogramming purposes, as it can be used as
+property keys like string. There are two types of
+symbols, local and global.
+Symbol-keyed properties of an object are not included in the output of
+`JSON.stringify()`, but the `util.inspect()` function includes them by
+default.
+
+Learn more about symbols at
+https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Symbol.
+
+## `Symbol(string)`
+
+Symbols created via `Symbol(string)` are local to the caller function.
+Note that `Symbol('hello') !== Symbol('hello')`.
+For this reason, we often use them to simulate private fields, like so:
+
+```js
+const kField = Symbol('kField');
+
+console.log(kField === Symbol('kField')); // false
+
+class MyObject {
+ constructor() {
+ this[kField] = 'something';
+ }
+}
+
+module.exports.MyObject = MyObject;
+```
+
+Note that Symbols are not _fully private_, as the data could be accessed
+anyway:
+
+```js
+for (const s of Object.getOwnPropertySymbols(obj)) {
+ const desc = s.toString().replace(/Symbol\((.*)\)$/, '$1');
+ if (desc === 'kField') {
+ console.log(obj[s]); // 'something'
+ }
+}
+```
+
+Local symbols make it harder for developers to monkey patch/access
+private fields, as they require more work than a property prefixed
+with an `_`. Monkey patching private API that were not designed to be
+monkey-patchable make maintaining and evolving Node.js harder, as private
+properties are not documented and can change within a patch release.
+Some extremely popular modules in the ecosystem monkey patch some
+internals, making it impossible for us to update and improve those
+areas without causing issues for a significant amount of users.
+
+## `Symbol.for`
+
+Symbols created with `Symbol.for(string)` are global and unique to the
+same V8 Isolate. On the first call to `Symbol.for(string)` a symbol is
+stored in a global registry and easily retrieved for every call of
+`Symbol.for(string)`. However, this might cause problems when two module
+authors use the same symbol
+for different reasons.
+
+```js
+const s = Symbol.for('hello');
+console.log(s === Symbol.for('hello'));
+```
+
+In the Node.js runtime we prefix all our global symbols with `nodejs.`,
+e.g. `Symbol.for('nodejs.hello')`.
+
+Global symbols should be preferred when a developer-facing interface is
+needed to allow behavior customization, i.e., metaprogramming.