Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
October 11, 2021 09:38 pm GMT

Javascript Symbols Classes =

Symbol is a built-in object whose constructor returns a symbol primitive also called a Symbol value or just a Symbol thats guaranteed to be unique. Symbols are often used to add unique property keys to an object that wont collide with keys any other code might add to the object, and which are hidden from any mechanisms other code will typically use to access the object.

In Javascript, Symbols are incredible resources for all sorts of use cases. However, I think many of the possibilities show their true colors when combined with classes. There are very many static Symbol properties that can be used with classes, although I'll only be going through a few of the most important. Check the rest out at the MDN page linked!

All of the below will work with any object, not just classes. I think classes simply demonstrate their usefulness the best

How to use static Symbol properties

As described in the top quote, symbols are unique. That means, if you create a symbol and attach it to an object as a property key (using bracket notation property accessors), the assigned value will only be accessible when using the same exact instance of that symbol.

const mySymbol = Symbol('foo');const obj = {  [mySymbol]: 'bar',};// undefined - 'foo' is only a descriptor// and doesn't actually do anythingobj.foo;// undefined - all symbols are uniqueobj[Symbol('foo')]; // 'bar' - obj[mySymbol];

With this mechanic, static Symbol properties were created (for mostly internal use) so that classes and objects can be more configurable without taking up any property names that you could use otherwise.

1. Symbol.iterator and Symbol.asyncIterator

Learn about iterators

This one's a biggie. Symbol.iterator and Symbol.asyncIterator will most notably specify the behavior of a class in for...of and for await...of loops respectively. Here's an example of it in action:

// a class representing a bookshelfclass Bookshelf {  // this functions is an iterator,  // so we prefix it with a `*`  // and use the `yield` keyword  *[Symbol.iterator]() {    yield 'Harry Potter';    yield 'The Tempest';    yield 'The Lion King';  }}

In this example, we are using Symbol.iterator to create an iterator that will be used to iterate through every book on the "bookshelf". I hard coded the values, but it a more realistic example, you'd probably want to dynamically yield every value in a predefined array (i.e. this.books).

class Bookshelf {  // ...}const bookshelf = new Bookshelf();for (const book of bookshelf) {  console.log(book);}

The above will log the following:

'Harry Potter''The Tempest''The Lion King'

It's like magic! The same can be used for Symbol.asyncIterator with for await...of

2. Symbol.toStringTag

This symbol is much less confusing than the above, but still very cool. Ever wondered why Object#toString() returns '[object Object]', Map#toString() returns '[object Map]', etc?

Your first guess might be that it uses constructor.name. However, we can debunk that because the following doesn't work:

class Book{}// '[object Object]' - not '[object Book]'new Book().toString();

Instead, they use Symbol.toStringTag to specify what tag they want to be attached.

class Book {  get [Symbol.toStringTag]() {    return 'Book';  }}// '[object Book]'new Book().toString();

Note that if you want your class to return something special when converted to a string that doesn't fit that format, you can simply overwrite the toString() method itself.

I'm sure there are many use cases for this, but I think it's best used for debugging (especially if you're creating a library and want to make it easy for the end user to troubleshoot). If you try to print some text and you find [object Object], it might be hard to find out what's causing it

However, if you get [object Boolean], [object Null], or a custom [object SomeClassName], I bet you it will be a lot easier.

3. Symbol.hasInstance

This symbol defines the behavior of instanceof when used with your class.

'hello world' instance of string; // true100 instance of string; // falseString[Symbol.hasInstance]('hello world'); // trueString[Symbol.hasInstance](100); // false

Here's an example of implementing it yourself:

class Book {  constructor(name, author) {    this.name = name;    this.author = author;  }  // `instance` is what's being compared  static [Symbol.hasInstance](instance) {    // `instance` is a `Book` if    // it has a name and author    return book.name && book.author;  }}// these are the fields we needconst name = 'Harry Potter';const author = 'J.K. Rowling';new Book(name, author) instanceof Book; // true{ name, author } instance of Book; // true

4. Symbol.species

This one's hard to wrap your head around. Symbol.species is most notably used internally for arrays and maps (although you can use it in your custom classes as well) to find what subclass should be created from methods that create new classes out of themselves... or something.

Talk is cheap  show me the code

Here's an example:

class CustomArray extends Array {}const arr = new CustomArray(1, 2, 3);// true - even though `Array#map` creates a *new* array,// it will dynamically access the constructor through `this.constructor`,// meaning it can automatically create derived classes when neededconsole.log(arr.map((num) => num * 2) instanceof CustomArray);

But, maybe you want to override that:

class CustomArray extnds Array {  static get [Symbol.species]() {    return Array;  }}const arr = new CustomArray(1, 2, 3);// false - this will now always create `Array`sconsole.log(arr.map((num) => num * 2) instanceof CustomArray);

Internally, arrays are deciding what class to consrtuct like so:

new (this.constructor[Symbol.species] || this.constructor)(/* ... */);

First it accesses Symbol.species to see if you have an override set up, then it falls back to the current constructor.

I hope you learned one or more new way to use the Symbol! If you have any questions, corrections, or addons, I would love to hear them. Peace


Original Link: https://dev.to/lioness100/javascript-symbols-classes-2b08

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To