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