diff options
author | Matteo Collina <hello@matteocollina.com> | 2018-09-04 12:10:01 +0200 |
---|---|---|
committer | Daniel Bevenius <daniel.bevenius@gmail.com> | 2018-09-07 09:23:03 +0200 |
commit | 4f5aa3607d84ad500e496fbffccd91b769cab259 (patch) | |
tree | 0817badf02830432d252f908d5fe28fb5d636d0a /doc/guides/using-symbols.md | |
parent | a1a0c5906338c62eeb4c9f3b9ee094862ec02dad (diff) | |
download | android-node-v8-4f5aa3607d84ad500e496fbffccd91b769cab259.tar.gz android-node-v8-4f5aa3607d84ad500e496fbffccd91b769cab259.tar.bz2 android-node-v8-4f5aa3607d84ad500e496fbffccd91b769cab259.zip |
doc: added symbols guidelines
PR-URL: https://github.com/nodejs/node/pull/22684
Reviewed-By: Tobias Nießen <tniessen@tnie.de>
Reviewed-By: James M Snell <jasnell@gmail.com>
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
Reviewed-By: Vse Mozhet Byt <vsemozhetbyt@gmail.com>
Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Anatoli Papirovski <apapirovski@mac.com>
Diffstat (limited to 'doc/guides/using-symbols.md')
-rw-r--r-- | doc/guides/using-symbols.md | 73 |
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. |