Skip to content

Instantly share code, notes, and snippets.

@abstractmachines
Last active February 23, 2018 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save abstractmachines/18ea0dc6b8b98e307e937806b772f974 to your computer and use it in GitHub Desktop.
Save abstractmachines/18ea0dc6b8b98e307e937806b772f974 to your computer and use it in GitHub Desktop.
Well Known Symbols : instanceof via custom Symbol.hasinstance
/* Well Known Symbols : Symbol.hasinstance
sources:
1 - https://www.keithcirkel.co.uk/metaprogramming-in-es6-symbols/
2 - http://exploringjs.com/es6/ch_symbols.html
3 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/instanceof
4 - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol/hasInstance
Well Known Symbols are Reflection via implementation in ES6.
Reflection in Metaprogramming: observing low level internals of a programming language/program.
One example of Well Known Symbols in JS is Symbol.hasInstance, which instanceof uses under the hood.
*/
// using instanceof :
function ClassyFunc() {}
let c = new ClassyFunc();
if (c instanceof ClassyFunc) {
console.log('instanceof.')
}
else {
console.log('not instanceof.')
}
// > instanceof
/* Let's implement that by hand.
Under the hood, instanceof uses (rhs)[Symbol.hasInstance](lhs),
where rhs is right hand side and lhs is left hand side.
Symbol is static scoped.
*/
class ArrayClass {
static [Symbol.hasInstance](input) {
return Array.isArray(input)
}
}
let a = []
let b = 3
console.log(a instanceof ArrayClass)
// > true
console.log(a instanceof ArrayClass)
// > false
@abstractmachines
Copy link
Author

abstractmachines commented Nov 2, 2017

There are many well known symbols

There are other "well known symbols" that are the implementation, under the hood, of JS functions.

For example, for of uses Symbol.iterator under the hood (somewhere in the prototype chain, one of the objects in that chain has an @@iterator; each time the for of is used, Symbol.iterator is invoked). More info on MDN.

Symbols are not the best choice for information hiding

The argument has been made that Symbols can be used for information hiding/encapsulation in JS, but that is not a complete encapsulation, as getters for Symbols/Reflect can still be used to access that data. See Dr Rauschmeyer's blog on information hiding with JS here - generally, using the Constructor or WeakMaps are preferred. Here's another blog post detailing how Firefox dev tools used WeakMaps for information hiding (encapsulation).

@abstractmachines
Copy link
Author

abstractmachines commented Feb 23, 2018

Instanceof lies. Typing matters

https://medium.com/@_ericelliott/javascript-does-not-have-static-types-69492ce923b5

"JavaScript does not have static types. What you’re asking for does not exist in the language.
Therefore there is no way to do a static type check that you can rely on in JavaScript.

That’s why instanceof lies and can be the source of lots of bugs or awkward restrictions.

Nominal types (type checking based on the name or identity of a single class/interface)
will never work well in JavaScript.

That’s why TypeScript (which adds static annotations and analysis on top of JavaScript) uses structural types,
which is basically automated duck typing."

  • Eric Elliott

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment