Python developer on Javascript land, plus some WH40k fun

pencillr

Richard Lenkovits

Posted on August 15, 2019

Python developer on Javascript land, plus some WH40k fun

First and foremost: if you've got the Warhammer40k references please press the unicorn, and leave a comment. Just wanna see how many loyal servants of the Emperor are here amongst us :D

No frontend without javascript

There was a point in my developer career about a year ago, when I realized that I just can't really avoid learning javascript if I want to create interactive web applications.

The revelation hit me hard, like a ramming Lunar Class Cruiser.

ships ramming in PC game Gothic Armada
Okay, maybe not that hard...

I must admit, I used to believe that javascript is an old, cumbersome, and even dangerous tool. If the topic came up at work, my colleagues (who are mostly backend and DevOps people) were all about how problematic and silly this language was in may ways.

What I didn't know back then is that they had experience with JS prior ES6, so with old javascript. And man, old javascript had its rough edges. It's clear why my colleagues had grudges.

Consequently, when I realized that I need JS I started looking for a shortcut. I really wanted to learn some fancy framework instead of doing it with vanilla javascript. And so came to React. Naively I thought React will save me from javascript.

It didn't. And you know what? It was still a good choice!

Why learn to swim in deep waters

I know I probably should say that "nah you must start with vanilla javascript", but for me starting with React resulted in an accelerated learning process! As a DevOps person, I'm originally more of a python/bash developer and I was never exposed to the webdev world. React pushed me to learn all about the javascript toolchain, and more. I needed to learn nodeJS, graphQL, Sass, a lot of nice tools and new libraries. It really worked out for me. Now one year has passed, and I've just finished my first official freelance frontend project!

So I figured I make a post about javascript for python devs!
Maybe I can save some struggle to those who happen to find themselves in my shoes, struggling why that empty array is not falsy. Or stuff like that.
Okay, lets, go!

primarch ship

Into the warp

I want to start with just a small list of peculiar things that might hit you when coming from python you start to write javascript code. These are things that you face pretty much straight on.

The void:

There are two ways in Javascript to express nothingness: undefined and null. Python has one: None.
Undefined is for variables or properties that do not exist or have not yet been assigned a value, while null represents the intentional absence of any value - when, say, you explicitly set something to null.

Type mess:

Python has a great type system. You've got lists, sets, tuples, dictionaries, not even mentioning things like Path from pathlib (types for paths) or the collections library. Javascript is not that versatile. - Python’s list and JavaScript’s Array are quite similar but probably that's where similarities end.

  • Since JavaScript has no mutable/immutable distinction, there is no JavaScript type corresponding to Python’s tuple.
  • Also, javaScript has no built-in hash-table support. JavaScript code that builds objects with curly brackets looks very similar to Python dictionaries, but what’s going on behind the scenes is completely different.
  • In javascript, mixing types can be dangerous. You never know what implicit conversion happens in the background.

The why!?

Semicolons. What about the semicolons? Should I use them? No? Cool. But wait. There are still some scenarios when I should? WTF?

Okay chill out. Actually, javascript does not strictly require semicolons. When there is a place where a semicolon was needed, a process called Automatic Semicolon Insertion adds it behind the scenes, while parsing of the source code happens. The problem is that it sometimes misinterprets what should be done.

Interpolation

In python there are a ton of ways to do interpolation, parameter expansion, and string concatenation. In javascript, you can use template strings almost like in bash but with backticks, which I think is pretty neat!

Booleans:

JavaScript has true and false. Python has True and False.

The Ritual

In python, we favor snake_case while in javascript it's camelCase.

Variable Scopes:

Python variables have global and functions scopes depending on where they were declared, and this can be further complicated with global and nonlocal keywords. Javascript variables, on the other hand, can be declared by using keywords let, const, var. Here let and const have a block scope but var has function scope. So for example, defining let outside of any function - contrary to var - does not create a global variable.

The Heresy:

In python, using global is heresy. In javascript using var is heresy.

List operations:

Let's see how some basic list operations differ.

Python Js
len(l) l.length
l.append(item) l.push(item)
l.pop() l.pop()
l.pop(0) l.shift()
l[start:end] l.slice(start, end)
[start:end] = […] l.splice(start, howMany, […])

Looping around

The more interesting issues came up when I was trying to do some basic data manipulation. I can't say that it wasn't a struggle sometimes.

spacehulk firefight

For example, when I first encountered a problem like this:

for weapon, damage in strike_map.items():
    print(
        "With battery {} dealt {} damage!".format(
            weapon, ", ".join(str(x) for x in damage)
        )
    )
# Where strike_map is:
# strike_map = {
#    "thermal lance": [6, 5, 4, 8],
#    "macrobattery": [4, 8, 9, 7]
# }

# Prints:
# With battery thermal lance dealt 6, 5, 4, 8 damage!
# With battery macrobattery dealt 4, 8, 9, 7 damage!
Enter fullscreen mode Exit fullscreen mode

I really like this example as it encompasses a lot about how smoothly one can manage loops in python. Let's see what we have here:

  • We have the hashmap strike_map -in python, called a dictionary-, that collects starship weapons and the damages dealt by them.
  • Then we use items() method which returns a list of a given dictionary’s (key, value) tuple pair. Then we iterate on it.
  • In the cycle using string format() method we print the weapons and the corresponding damages as a string.
  • The tricky part is the list comprehension, one of the best features in python, and in many functional programming languages.
str(x) for x in damage
Enter fullscreen mode Exit fullscreen mode

This will return the list of the numbers in the damage list, but it also executes the str() function on every element to stringify them, so they can be joined together to a single string, separated by commas.

Beautiful right?

Now let's see this in Javascript. We don't have hashmaps, so our data can be represented by an object.

const strike_map =  {
    thermal_lance: [6, 5, 4, 8],
    macrobattery: [4, 8, 9, 7]
}
Enter fullscreen mode Exit fullscreen mode

Now you have Object methods so you can return keys or values with Object.keys(), Object.values(). Maybe the closest could be Object.entries() that returns an array of a given object's own enumerable string-keyed property [key, value] pairs.
So this:

[ [ 'thermal_lance', [ 6, 5, 4, 8 ] ],
  [ 'macrobattery', [ 4, 8, 9, 7 ] ] ]
Enter fullscreen mode Exit fullscreen mode

With this we can have a not so neat, but still effective solution:

for (let [weapon, damage] of Object.entries(object1)) {
  console.log(`With battery ${weapon} dealt {damage} damage!`);
}
// prints:
// thermal_lance: 6,5,4,8
// macrobattery: 4,8,9,7
Enter fullscreen mode Exit fullscreen mode

Now you could say we've made it, but this way we'd let javascript to do implicit type conversions in the background - which we should not rely on. Now when I'm writing this post array comprehensions are deprecated in javascript and the new solution is still in an experimental phase. I didn't find a better way than to use an inner for...of loop, or the Array map() method which can be quite as compact using arrow functions.

Here I challenge you JS gurus, to show me how you would do this simple nested iteration problem the cleanest way.

Arrow functions

In javascript, there are regular functions, which are not prefered right now.

function name(parameter1, parameter2, parameter3) {
  // code to be executed
}
Enter fullscreen mode Exit fullscreen mode

And there are these new arrow functions. They can take many forms, so at first, I did find them really messy because of the loose syntax.

See a few cases:

// Assigning:
const exampleFunc = function() {
//...
}
// or:
const exampleFunc = () => {
//...
}
// or:
const exampleFunc = (param1, param2) => doStuff(param1, param2)
// without parentheses
const exampleFunc = param => doStuff(param)
// Implicit returning?!
const exampleFunc = () => 'test'
// add parentheses when returning an object? Ok.
const exampleFunc = () => ({ value: 'test' })
Enter fullscreen mode Exit fullscreen mode

Another tricky thing with arrow functions is that the this scope is inherited from the execution context. Due to this, arrow functions are not suited as object methods.

So this will not work:

const IronTide = {
    class: 'Tempest',
    size: 'frigate',
    wholeType: () => {
        return `${this.class} class ${this.size}`
    }
}

// THIS WILL RETURN "undefined class undefined" :
Enter fullscreen mode Exit fullscreen mode

Async

If you're using javascript you're probably developing web apps, and in web apps sometimes you need to run queries and operations that you want to run in the background, without blocking the user who's clicking around. So obviously you will need async operations.

Coming from python this was the first thing that gave me some hard time. Even though async was not totally foreign to me, as I actually had experience with asyncio in python backend projects, but it's still weird sometimes especially if your brain is used to the synchronous world.

If you're getting into the javascript world you should definitely read up on these things. I promise it will be really beneficial.

Packages

I must admit, package management is probably harder in python. Managing venv, and your requirements.txt is just a little more tedious than doing it in javascript.
In JS you've got a lot of options, I'm personally using yarn. With it, it's super easy to manage your libraries and keep them updated.

That was all about it! I know we've just scratched the surface but I hope it could help you Pythonistas in this ruthless age of web applications! Take care in the fathomless void of web development my friend. And remember. In the darkness, follow the holy light of Terra Clean Code!

spire interrogated

💖 💪 🙅 🚩
pencillr
Richard Lenkovits

Posted on August 15, 2019

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related