Symbols Are Your Friend Series
- Part I: A Gentle Introduction
- Part II: Symbol.for() & Symbol.keyFor()
- Part III: Symbol.iterator
- Part IV: Symbol.search, Symbol.split, & Symbol.species
- Part V: Symbol.toPrimitive, Symbol.toStringTag, & Symbol.unscopables
- Part VI: Symbol.match, Symbol.matchAll & Symbol.replace
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);
}
})();
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
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"]
const pokemon = ['Eevee', 'Snorlax', 'Ditto'];
const transformers = ['Jazz', 'Grimlock', 'Arcee'];
transformers[Symbol.isConcatSpreadable] = false;
pokemon.concat(transformers);
// Returns ["Eevee", "Snorlax", "Ditto", Array(3)]
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"]
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.
Top comments (0)