DEV Community

JS Bits Bill
JS Bits Bill

Posted on • Edited on

2 1

Symbols Are Your Friend Series Part VII: Symbol.asyncIterator, Symbol.hasInstance & Symbol.isConcatSpreadable

Symbols Are Your Friend Series


This is it - the last of the well-known symbols! Today we'll look at:

  • Symbol.asyncIterator
  • Symbol.hasInstance
  • Symbol.isConcatSpreadable

Symbol.asyncIterator
Similar to Symbol.iterator, Symbol.asyncIterator functions the same way, except they return promises. This enables us to make an object that has asynchronous functionality iterable:

// Create iterable object
const todos = {
  [Symbol.asyncIterator]: function() {
    let i = 1;
    const limit = 4;

    return {
      async next() {
        if (i === limit) return { done: true };

        i++;
        return { value: await fetchTodo(i), done: false }
      }
    }
  },
};

// Fetch a todo object
async function fetchTodo(num) {
  const url = `https://jsonplaceholder.typicode.com/todos/${num}`;
  const response = await fetch(url);
  return await response.json();
}

// Asynchronously iterate through todos
(async () => {
  for await (const todo of todos) {
    console.log(todo.title);
  }
})();
Enter fullscreen mode Exit fullscreen mode

With this example, we're effective making our todos object async iterable. Symbol.asyncIterator is also commonly implemented with generator functions but we'll explore those in another article.


Symbol.hasInstance
This symbol is used to determine whether or not a constructor has an instance of another object when instanceof is used.

This allows us to customize the behavior of instanceof when it operates on our constructor object:

class PowerRanger {
  constructor(name) {
    this.name = name;
  }

  static [Symbol.hasInstance](instance) {
    const rangersRegEx = /jason|zack|kim|billy|trini/i;
    return rangersRegEx.test(instance.name);
  }
}

const jason = new PowerRanger('Jason');
const bob = new PowerRanger('Bob');

jason instanceof PowerRanger; // true
bob instanceof PowerRanger; // false
Enter fullscreen mode Exit fullscreen mode

Symbol.isConcatSpreadable
This symbol is a toggle that indicates if an object should be flatted when Array.prototype.concat() is used:

const pokemon = ['Eevee', 'Snorlax', 'Ditto'];
const transformers = ['Jazz', 'Grimlock', 'Arcee'];

pokemon.concat(transformers);
// Returns ["Eevee", "Snorlax", "Ditto", "Jazz", "Grimlock", "Arcee"]
Enter fullscreen mode Exit fullscreen mode
const pokemon = ['Eevee', 'Snorlax', 'Ditto'];
const transformers = ['Jazz', 'Grimlock', 'Arcee'];

transformers[Symbol.isConcatSpreadable] = false;

pokemon.concat(transformers);
// Returns ["Eevee", "Snorlax", "Ditto", Array(3)]
Enter fullscreen mode Exit fullscreen mode

A great use for this Symbol is to force normally unflattenable array-like objects to flatten:

const pokemon = ['Eevee', 'Snorlax', 'Ditto'];
const transformers = {
  [Symbol.isConcatSpreadable]: true, 
  length: 3, // Length needed to specify # of props to add
  0: 'Jazz', 
  1: 'Grimlock',
  2: 'Arcee'
};

pokemon.concat(transformers);
// Returns ["Eevee", "Snorlax", "Ditto", "Jazz", "Grimlock", "Arcee"]
Enter fullscreen mode Exit fullscreen mode

This concludes the Symbols Are Your Friend series! We've just gone from Symbol zero to hero! 🦸


Check out more #JSBits at my blog, jsbits-yo.com. Or follow me on Twitter.

AWS GenAI LIVE image

Real challenges. Real solutions. Real talk.

From technical discussions to philosophical debates, AWS and AWS Partners examine the impact and evolution of gen AI.

Learn more

Top comments (0)

Postmark Image

Speedy emails, satisfied customers

Are delayed transactional emails costing you user satisfaction? Postmark delivers your emails almost instantly, keeping your customers happy and connected.

Sign up

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay