< žanderle />

Developer by Day, Boardgamer by Night.

< Just Some Musings

5 JavaScript things you should know/understand as a Python Developer

Modern JavaScript is in many ways very similar to Python. But it's also very different. I notice a lot of Python developers don't really leverage those similarities and aren't too familiar with the differences. Which is a shame. If you're a Python developer trying to become better at JavaScript, there are a few things that you could learn that would really level up your JavaScript knowledge. Let's check them very quickly. In no particular order these are:

1. Async and event loop

When we run JavaScript code in a browser we have to be aware that the user expects the interface to run normally, even if there is some computing happening in the background. But that isn't just handled automatically. We have to use asynchronous code to make it happen. And that is different from how we usually approach problems in Python. Of course there are cases where you want to do async stuff in Python as well, but doing everything synchronously is still the baseline. This fundamental difference is something that often makes Python developers trip when they approach problems in JavaScript.

When it comes to async, the bare minimum you should know is how to use Promises. Understanding how to use async/await can also be very useful (especially since it's quite similar to Python's asyncio library), but don't skip on understanding Promises since async/await is just syntactic sugar around them.

Here are some great resources on how to use Promises:

Promise Basics

Using Promises

One thing regarding JavaScript and async that has always confused me is the fact that JavaScript is single-threaded. It will always run only one thing at a time. So where does async come from?! That part is solved by JavaScript runtime environment (browser, node, or something else), which provides an event loop. I think some base level understanding of how your JavaScript code is actually ran in the browser is very useful. Check out this talk on event loop. It is excellent at explaining not just how the event loop works, but also how all the pieces (JavaScript Engine, WebAPIs, event loop, etc) come together. I really recommend you watch this one, if you want to understand this topic a bit better.

2. ES6 and beyond

Even though ES6 came out over 5 years ago, a lot of people still haven't looked at everything the newer versions of JavaScript brought us. Since ES6, JavaScript has a lot of syntax that should be very familiar to you as a Python developer. And if you were frustrated with JavaScript back in the day, the modern syntax solves a lot of the most common problems.

Some of the most handy and common examples are:

  • object destructuring and object property shorthand

    const { a, b } = someObject;
    // Equivalent to 
    // const a = someObject.a;
    // const b = someObject.b;
    const newObject = { a, b };
    // Equivalent to
    // const newObject = { a: a, b: b };
    
  • arrow functions

    // A great way to define anonymous functions
    someArray.map(element => {
      const changed = doSomeComputation(element);
      return changed;
    });
    // But also allows for a more intuitive handling of current object context
    const myObject = {
      array: [1, 2, 3],
      multiplier: 3,
      multiply() {
        return this.array.map(element => element * this.multiplier);
      },
      // Without arrow functions you would have to do something like
      multiplyAlt() {
        const that = this;
        return this.array.map(function(element) { return element * that.multiplier; });
      }
    }
    
  • modules (import/export): lets you break your code into separate modules

    // myModule.js
    export someFunction;
    
    // main.js
    import { someFunction } from 'myModule';
    
  • template literals: very similar to Python's f strings

    const variable = 1;
    const myString = `{variable + 3} items`;
    
  • rest parameter and spread operator: similar to how *args works in Python functions

    function count(...args) {
      return args.length;
    }
    const array = [1, 2, 3];
    const anotherArray = [10, 11, ...array]; // [10, 11, 1, 2, 3]
    count(...array); // Same as count(1, 2, 3)
    
  • classes: prototypal inheritance confuses people, so ES6 introduced the more familiar classes. The following should be easy to read:

    class Shape {
        constructor (id, x, y) {
            this.id = id
            this.move(x, y)
        }
        move (x, y) {
            this.x = x
            this.y = y
        }
    }
    class Circle extends Shape {
        constructor (id, x, y, radius) {
            super(id, x, y)
            this.radius = radius
        }
    }
    const circle = new Circle(1, 10, 10, 100);
    circle.move(20, 40);
    
  • generators: again, this should be very familiar to any Python developer

    function* range (start, end, step) {
        while (start < end) {
            yield start
            start += step
        }
    }
    
    for (let i of range(0, 10, 2)) {
        console.log(i) // 0, 2, 4, 6, 8
    }
    

3. Build process

The build process is often cast aside as something you don't need to get into just yet. Or something you don't need to worry about if you just want to understand the code. Maybe that's technically true, but I think it can be very valuable to take the time to understand it. I recommend you approach it by either understanding what the build steps in an existing project are (whether it's using webpack, snowpack, gulp, grunt, or anything else), or setting up a simple build process for your project yourself.

I know for me personally, Webpack (and similar tools) was always such a mystery. Whenever I joined a project, all I ever knew was I had to run npm run dev and npm run build and that's it. And having this big black box in the middle of the code base made me feel unconfident. But after I've learned more about how it works on a specific example, I realized it's not that scary. It's just very verbose. And that has helped me tremendously both with understanding and with being able to tackle the problems in the project with confidence.

4. Differences between JavaScript and Python

There are a few things in JavaScript that are slightly different from Python, so it's easy to miss them.

  • Truthiness of empty objects and lists

    const emptyList = [];
    const emptyObject = {};
    if (emptyList) {
      console.log('Empty list is truthy');
    }
    // Outputs 'Empty list is truthy'
    if (emptyObject) {
      console.log('Empty object is truthy');
    }
    // Outputs 'Empty object is truthy'
    
  • Variables: you have to use var, let, or const when defining variables in JavaScript.

  • for...in: sounds similar to iterating in Python. But it's not.

    const array = ['a', 'b', 'c'];
    for (let item in array) {
      console.log(item);
    }
    // Outputs 0, 1, 2
    // What you actually want is for...of
    for (let item of array) {
      console.log(item);
    }
    // Outputs 'a', 'b', 'c'
    
  • Checking for equality: in JavaScript you have == but also ===. You usually want === because it will check equality by checking both the value and the type, whereas == will only check the value -- if the values being compared aren't of the same type, it will convert them, and that can lead to some unexpected results. To be on the safe side, you should always use ===

5. Functional programming

Have you ever seen someone doing something like this in Python (and then complain how Python sucks):

for i in range(0, len(my_list)):
    element = my_list[i]
    print(element)

Well, similar thing happens to JavaScript ALL THE TIME. One of the common problems is that people don't embrace the functional programming capabilities of the language, because they're too used to solving problems through OOP. Here's a good talk if you're not familiar with functional programming.

There's a lot to be said here, but generally speaking, I think Python developers coming to JavaScript are usually underutilizing things like map, filter, reduce and anonymous functions.

// Instead of doing this:
const array = [1, 2, 3];
let newArray = [];
for (let el of array) {
  newArray.push(el * 2);
}
// newArray [2, 4, 6];
// Do it like this:
const newNewArray = array.map(el => el * 2);

Conclusion

That was a very brief overview. If this is something you'd be interested in learning more about (with actual explanations and examples, not just skimming over), check out the course I'm building: Modern JavaScript for Python Developers. It's designed to leverage your Python skills to really get a handle on JavaScript. You'll learn all the places where your Python knowledge translates easily, and all the places where JavaScript is very different. That way your learning will be very efficient, because you won't waste time on concepts/syntax you're already familiar with. Instead, you'll be able to focus on stuff that's tricky and unexpected.

Visit the website and sign up to the mailing list to be notified when the course will be released.