Jenn Wong Civil ➡️ software engineer. Conf speaker. Creator of (Human) Wasteland & I ❤️ food, code, & sleep. SF native. My audacity knows no bounds.

How Python can help you learn ES6

5 min read 1539

“Have you learned ES6 yet?”

Oof. I used to feel a sense of pressure when people would ask me that. In the end, I learned ES6 with the help of Python. Strange, huh? Turns out, a bunch of syntax is shared between the two languages, so they go hand in hand in a way.

In this post, we’ll look at how Python can help you learn ES6.

Basic differences between Python and ES6

Before we get into how similar JavaScript and Python are, I first want to talk about some key differences. For example, whitespace in JavaScript doesn’t matter at compile time, but it sure does in Python. Python relies on indentation to determine the grouping of statements.

Primitives in JavaScript and Python are also quite different. Check out the table below which details the primitives of both languages. You’ll see that they overlap a bit with their representations of Booleans and nothing, but beyond that, they’re distinct.

Table of primitives in JavaScript versus Python

One last, basic difference to note about JavaScript and Python is that JavaScript allows type coercion. The following code blocks demonstrate coercing a number to a string in JavaScript, but an impossibility in Python!

// You can coerce an integer into string in JavaScript
let coerced = 1;
let concatenated = coerced + 'string';
# You can't coerce an integer into a string in Python
not_coerced = 1
concatenated = str(not_coerced) + 'string'
Coercion demonstrated in JavaScript and in Python

Functions or.. methods?

Functions and conditionals have extremely similar structures in both JavaScript and Python. For example:

function drSeuss(catInTheHat, thing1, thing2) {
  if (catInTheHat == true &&
    thing1 == true &&
    thing2 == true) {
    console.log('is cray');
  } else if (catInTheHat != true) {
  } else {
    console.log('so boring');
def dr_seuss(cat_in_the_hat, thing1, thing2):
  if cat_in_the_hat == True and
    thing2 == True and
    thing2 == True:
    print 'is cray'
  elif cat_in_the_hat != True:
    print 'boring'
    print 'so boring'

I hadn’t thought too much about this, but with JavaScript, the idea of “methods” often refers to methods that are built into the specification of the language, e.g. `Function.prototype.apply()`.

From MDN:

In most respects functions and methods are identical except for two key differences:

A method is implicitly passed the object on which it was called.

A method is able to operate on data that is contained within the class.

Because classes don’t truly exist in JavaScript, the function and method example below is represented in Python only (more on ES6 classes later in this article).

def fish_and_chips():
  ingredients = ['fish', 'potatoes', 'batter']
  print 'cooking %s together' % (', '.join(ingredients))

# cooking fish, potatoes, batter

class Baking(object):
  def __init__(self, supplies): = supplies

  def bakewell_tart(self):
    ingredients = ['almonds', 'raspberry', 'icing sugar']
    print self
    print 'baking %s' % (', '.join(ingredients))

# <__main__.Baking object at 0x10d6e0510>
A function versus a method in Python

Ok, onto some of the ways Python pushed me to learn more about ES6!

Block scope

When I first started learning JavaScript (back in “ancient” ES5 days), I thought many structures in the language created scope. I thought that blocks inside of conditionals statements created scope. I found that only functions create scope in JavaScript.

With the addition of const and let to ES6, we get block scope!

function simpleExample(value) {
  if (value) {
    var varValue = value;
    let letValue = value;
    console.log(varValue, letValue); // value value
  // varValue is available even though it was defined
  // in if-block because it was "hoisted" to function scope
  console.log(varValue); // value
  // letValue is a ReferenceError because 
  // it was defined within the if-block
  console.log(letValue); // Uncaught ReferenceError: letValue is not defined

What else creates scope in JavaScript, ES6, and Python? And what type of scope do they use? Check out the following table:

Template literals

I often think of template literals as Mad Libs. In case you didn’t grow up with Mad Libs, they were short stories which you could fill in with your own content. Sentences were missing words, and you could write anything you wanted into those spaces. You only had to conform to the specified word type: noun, pronoun, verb, adjective, exclamation.

Mad Libs that read things like:

mothers sit around burping. Last summer, my little brother fell in a/an hairdo and got poison palmtree all over his butt. My family is going to Winsconsin, and I will..

Similar to Mad Libs, template literals are string literals that allow embedded expressions. They were originally called “template strings” in prior editions of the ES2015 specification.

Yup, these already existed in Python before ES6 was released. I had actually learned about literal string interpolation in Python, which made it that much easier for me to understand template literals in ES6. They are great because you no longer need the concatenation found in older versions of JavaScript which could get a bit ridiculous and coerce other types into strings.

let exclamation = 'Whoa!';
let sentence = `They are really similar to Python.`;
console.log(`Template Literals: ${exclamation} ${sentence}`);
// Template Literals: Whoa! They are really similar to Python.
print '.format(): {} {}'.format('Yup.', 'Quite!')
# .format(): Yup. Quite!

Default parameters

Yup, Python has had these forever too. Default parameters set a default for function parameters. This is most effective for avoiding bugs that arise when arguments are missing. And with the advent of ES6, JavaScript gained default parameters too.

function nom(food="ice cream") {
  console.log(`Time to eat ${food}`);
nom(); // Time to eat ice cream
def nom(food="ice cream"):
  print 'Time to eat {}'.format(food)
nom() # Time to eat ice cream

Rest parameters & *args

Rest parameter syntax allows us to represent an indefinite number of arguments as an array. In Python, they’re called *args, which again, I’d already learned before ES6! Are you sensing a pattern here?

Check out how each of the languages bundles parameters up in neat little packages:

function joke(question, ...phrases) {
  for (let i = 0; i > phrases.length; i++) {

let es6Joke = "Why does JS single out one parameter?"
joke(es6Joke, "Because it doesn't", 'really like', 'all the REST of them!');
// Why does JS single out one parameter?
// Because it doesn't
// really like
// all the REST of them!
def pirate_joke(question, *args):
  print question
  for arg in args:
    print arg
python_joke = "What's a Pyrate's favorite parameter?"
pirate_joke(python_joke, "*args!", "*arrgs!", "*arrrgs!")
# What's a Pyrate's favorite parameter?
# *args!
# *arrgs!
# *arrrgs!


Now, let’s look at prototypal inheritance! ES6 classes are actually syntactic sugar and based on the prototype chain found in ES5 and previous iterations of JavaScript. So, what we can do with ES6 classes is not much different from what we do with ES5 prototypes.

Python has classes built in, allowing for quick and easy object-oriented programming. I always found the prototype chain extremely confusing in JavaScript, but looking at Python and ES6 classes side by side really made sense to me.

To explain what the JavaScript prototype is, here’s a quote from MDN:

When it comes to inheritance, JavaScript only has one construct: objects. Each object has an internal link to another object called its prototype. That prototype object has a prototype of its own, and so on until an object is reached with null as its prototype. null, by definition, has no prototype, and acts as the final link in this prototype chain.

Let’s take a look at these ES6 “classes” based on the prototype chain:

class Mammal {
  constructor() {
    this.neocortex = true;
class Cat extends Mammal {
  constructor(name, years) {
    super(); = name;
    this.years = years;
  eat(food) {
    console.log('nom ' + food);
let fryCat = new Cat('Fry', 7);'steak');
class Mammal(object):
  neo_cortex = True
class Cat(Mammal):
  def __init__(self, name, years): = name
    self.years = years
  def eat(food):
    print 'nom %s' % (food)
fry_cat = Cat('Fry', 7)'steak')

A big difference between ES6 Classes and ES5 Prototypes: you can inherit more easily with classes than with the prototype chain. This is very similar to Python’s structure. Neat!

So there you have it. A bunch of examples of how Python helped me learn all about ES6. Often with programming languages, many differences exist, but so do many similarities. And it’s in those similarities that we can more easily learn new languages!

Plug: , a DVR for web apps

 is a frontend logging tool that lets you replay problems as if they happened in your own browser. Instead of guessing why errors happen, or asking users for screenshots and log dumps, LogRocket lets you replay the session to quickly understand what went wrong. It works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store.

In addition to logging Redux actions and state, LogRocket records console logs, JavaScript errors, stacktraces, network requests/responses with headers + bodies, browser metadata, and custom logs. It also instruments the DOM to record the HTML and CSS on the page, recreating pixel-perfect videos of even the most complex single-page apps.


Jenn Wong Civil ➡️ software engineer. Conf speaker. Creator of (Human) Wasteland & I ❤️ food, code, & sleep. SF native. My audacity knows no bounds.

Leave a Reply