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 Q Developer image

Your AI Code Assistant

Automate your code reviews. Catch bugs before your coworkers. Fix security issues in your code. Built to handle large projects, Amazon Q Developer works alongside you from idea to production code.

Get started free in your IDE

Top comments (0)

Billboard image

The Next Generation Developer Platform

Coherence is the first Platform-as-a-Service you can control. Unlike "black-box" platforms that are opinionated about the infra you can deploy, Coherence is powered by CNC, the open-source IaC framework, which offers limitless customization.

Learn more

👋 Kindness is contagious

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

Okay