Symbols Are Your Friend Part V: Symbol.toPrimitive, Symbol.toStringTag, & Symbol.unscopables
Tags: javascript
Published: 2020-11-03 19:01:26

<b>Symbols Are Your Friend Series</b>
  - [Part I: A Gentle Introduction](https://dev.to/js_bits_bill/symbols-are-your-friend-a-gentle-introduction-js-bits-23af)
  - [Part II: Symbol.for() & Symbol.keyFor()](https://dev.to/js_bits_bill/symbols-are-your-friend-part-ii-symbol-for-symbol-keyfor-js-bits-3clc)
  - [Part III: Symbol.iterator](https://dev.to/js_bits_bill/symbols-are-your-friend-part-iii-symbol-iterator-js-bits-18c4)
  - [Part IV: Symbol.search, Symbol.split, & Symbol.species](https://dev.to/js_bits_bill/symbols-are-your-friend-part-iv-symbol-search-symbol-split-symbol-species-js-bits-4i25)

---

I know. You haven't gotten your fill of symbols yet. Rest assured, there's more! This week, we'll take a look at the following symbol static properties:

<ul>
  <li><code>Symbol.toPrimitive</code></li>
  <li><code>Symbol.toStringTag</code></li>
  <li><code>Symbol.unscopables</code></li>
</ul>

---

<b><code>Symbol.toPrimitive</code></b>
This symbol defines the method to convert an object to a primitive.

Default behavior:
```js
const arr = [1, 2, 3];
`${arr}`; // "1,2,3"
```

<code>Symbol.toPrimitive</code> utilization:
```js
const arr = [1, 2, 3];
arr[Symbol.toPrimitive] = function(type) {
  const doubled = arr.map(item => {
  	return item * 2;
  });

  return `doubled: ${doubled}`;
};
`${arr}`; // "doubled: 2,4,6"
```

---

<b><code>Symbol.toStringTag</code></b>
This symbol defines the behavior of an object when it is converted into its default string description. Essentially it lets you modify the value of <code>Object</code> in <code>"[object Object]"</code> when <code>Object.prototype.toString()</code> is used:

Default behavior:
```js
const shows = {
	cartoon: 'DuckTales',
	sitcom: 'Seinfeld',
	crime: 'NCIS'
};
Object.prototype.toString(shows); // "[object Object]"
```

<code>Symbol.toStringTag</code> utilization:
<i>Note that <code>Symbol.toStringTag</code> is a string valued property (and not a method)</i>.
```js
const shows = {
  cartoon: 'DuckTales',
  sitcom: 'Seinfeld',
  crime: 'NCIS'
};
shows[Symbol.toStringTag] = 'Shows';
shows.toString(); // "[object Shows]"
```

One thing that's odd about this symbol is that it does not seem to work with anything other than objects:
```js
const arr = [1, 2, 3];
arr[Symbol.toStringTag] = 'Numbers';
Object.prototype.toString(arr); "[object Object]"
```

```js
const str = 'My string';
str[Symbol.toStringTag] = 'Custom String';
Object.prototype.toString(str); "[object Object]"
```

If anyone knows why, please comment!

---

<b><code>Symbol.unscopables</code></b>
This symbol is so incredibly useless but it at least introduced the <code>with</code> statement to me which I had never see before. Essentially, <code>Symbol.unscopables</code> modifies the behavior of <code>with</code>. So what exactly does that do?

<code>with</code> allows you to create a scope to a statement. The syntax is as follows:
```
with (expression)
  statement
```

Here's an example:
```js
with ({ first: 'Charles', last: 'Bronson' }) {
  console.log(`Hi ${first} ${last}!`);
  // Logs "Hi Charles Bronson!
}
```

So yeah, that's all it does. Also note that <code>with</code> is deprecated as it has browser compatibility issues.

So all <code>Symbol.unscopables</code> allows you to do is define what properties of an object are excluded from a <code>with</code> environment binding:

```js
const actor = {
  first: 'Charles',
  last: 'Bronson'
};

actor[Symbol.unscopables] = {
  last: true
};

with (actor) {
  console.log(first); // Logs "Charles"
  console.log(last); // Logs ReferenceError
}
```

More symbols in the next article! 😀

----------
Check out more #JSBits at my blog, [jsbits-yo.com](http://jsbits-yo.com/). Or follow me on [Twitter](https://twitter.com/JS_Bits_Bill).