Notes from Kyle Simpson, My JavaScript Spirit Guide

Posted January 20, 2018 in Research, Tutorials+Tips

I recently completed Kyle Simpson‘s “Deep JS Foundations” course on Frontend Masters and, let me tell you…that is the best $40 I’ll spend this month, by far! Kyle is not only brilliant, but an excellent and articulate teacher and I declare him my new JavaScript Spirit Guide. The course material and his teaching style are just what I needed – I want to understand more of JavaScript itself, not its features or syntax, and I have a hell of a time sitting through screencasts.

A few notable takeaways from “Deep JS Foundations”:

Don’t stop using var

let is the new var, right? Wrong! let, var, and const all serve different, nuanced purposes and are intended to be used together. I’m still in the process of fully understanding those nuances, but in short, use let if you need to scope a variable to a block i.e. something smaller than a function, like an if statement or for loop.

Here’s an example from chapter 3 of Kyle’s book, You Don’t Know JS (these are all free online!):

var foo = true;

if (foo) {
    let bar = foo * 2;
    bar = something( bar );
    console.log( bar );

console.log( bar ); // ReferenceError

If that is the functionality you want, use let. Defining variables with let at the global or function scope level does exactly the same thing as var, and eliminates the readability gains of using let at the block level. At least I think that’s how it works!

Name your function expressions

In JavaScript, we see anonymous functions all the time and we write them all the time. Here’s what a named vs. anonymous expression looks like:

var desc = function getDesc() { // named
    // ...

var desc = function() { // anonymous
    // ...

Of course, this means not using arrow functions as you’ll get a syntax error if you try to name one. A lot of Kyle’s viewpoints favor readability over concise, trendy code. I like that. Plus, you will generally get more informative stack traces when errors arise, though it seems that the engine (or compiler? not sure the right term here) does infer function names to some extent.

I don’t know enough to have an opinion here, but it does seem like erring on the side of readability is a good choice!

ES6 classes are duct tape, be careful

In the course, Kyle does not hesitate to identify how horribly designed certain parts of JavaScript are, and ES6 classes are one of those parts. In short, JavaScript was not designed with classical inheritance – it was designed with its own, weird prototypal inheritance. Adding the class syntax to JavaScript is obscuring its core characteristics in favor of nicer syntax, but if you try to “color outside the lines”, as he put it in the course, there are some serious gotchas.

Read more in this section of You Don’t Know JS, and on this exceptionally opinionated Github repo (🚨).

Implicit vs. Explicit Coercion

Coercion is when you change a piece of data into a different data type. For example, in JavaScript, the String "0" would coerce into the Number 0. Similarly, the Number 0 would coerce to the Boolean false. Note that I am capitalizing String, Number, and Boolean because they are three of the six official primitive data types in JavaScript.

One can practice explicit coercion by explicitly transforming data types into others, like so:

>> "text" + String(12);
 > "text12"

…verses implicitly coercing the data, i.e. letting JavaScript do it behind the scenes, automatically:

>> "text" + 12;
 > "text12"

In many other programming languages, the above would cause an error. Not in JavaScript! As you can see in these examples, explicit indicates you, the reader of my code, can see what will be coerced while in the implicit example, it happens magically. It’s a common assumption that implicit coercion is bad news bears. It certainly can be, but as Kyle points out in the course, we use implicit coercion frequently.

As long as the code is understandable, they aren’t necessarily bad:

var amount_val = document.querySelector("amount_input").value;
var amount_num = +amount_val; // + coerces String to Number
var is_enough = amount_val > 100; // Boolean 

if( is_enough ) {
    // ....

== is not evil

Many of us have heard the gospel: double equals is weird, always use triple equals for comparisons. As my JavaScript spirit guide, Kyle, points out, this is a rule rooted in misunderstanding.

The common assumption is that ==, or “loose equality”, checks the only the value, and ===, or “strict equality” compares both value and type. Not the case, as I now know! The true difference between the two is that == allows coercion and === disallows coercion. That’s why, for example, 0 == "0" returns true, and 0 === "0" returns false: the == coerces the Number 0 into a String and finds them equal. Here’s a plain language summary from the Mozilla docs:

Strict equality compares two values for equality.

Loose equality compares two values for equality, after converting both values to a common type.

So, if coercion is a problem use ===, if it’s not a problem – or even be helpful – then == is your friend!

Finally, linters do not replace humans

I wish I wrote enough JavaScript day-to-day to fully appreciate this claim, but I get the gist and I like it. A linter might tell you to never use ==, or to always use let, but at the end of the day its a more future-proof strategy to be your own linter.

Okay, that’s all for now! Yes, “Deep JS Foundations” clocks in at a hefty 9 hours and change, but not if you watch it at 1.8x 🤗! Go subscribe to Frontend Masters, and Kyle Simpson can be your JavaScript spirit guide, too.


What do you think? Do you have any questions, thoughts, or related links to share? Did I make a mistake in my post?

  • yeah he is amazing.. the bad part is i have to use frameworks that go against his philosophy since i am just a lowly corporate worker right now

    Compose a Reply

  • Everything Kyle said is correct.
    var, let, const are all good but let can fully replace var. No gotchas at all except that it lets you stop hidden bugs.

    //case 1
    function showName(name){
    if(typeof name === "string") {var person1 = name;}
    showName([]); //alerts undefined

    //case 2
    function showName(name){
    if(typeof name === "object"){let person2 = name;}
    alert (person2);
    showName("Michael Iyke");//Throws an error
    What is happening is that even though our if statement returns false, because of var keyword, person1 is still declared but not initialized to any value. But in case2, let keyword makes sure the expected error is thrown. This also respects the behavior of block scoping.
    with let we'd have
    function showName(name){
    let person2; //I have declared it but not initialized
    if(typeof name === "object"){person2 = name; }
    showName("Michael Iyke"); //alerts undefined and no error
    Implicit and explicit coercion are both used in everyday practice but most people favor implicit to reduce the amount of character strokes typed.
    == vs ===
    The difference is small. You don't bump into their collision all the time. To be safe, it is a common in practice to use == for ordinary comparison and === for type comparisons. eg
    ordinary checks
    if (i == "skipWaiting"){

    type checks
    if(typeof data === "object"){
    //don't use == here. Possible but not good practice
    for(var i in data) {var datum = data[i]; doSthWith(datum);}

    Compose a Reply

Submit a Comment