Let’s talk about Javascript

This video is amazing/hilarious, and the inspiration for this article

I’m a ‘JS Engineering Intern’ at Behance. Thus, I must JS. And if you JS for long enough, you shall find darkness

Bitwise complement and indexOf

> ~'abc'.indexOf('d')

Is that a bitwise operator in javascript?

Yes. This is roughly equivalent to:

> 'abc'.indexOf('d') !== -1


Remember your freshman year computer science class where you learned how 2's complement works, and that -1 will be represented by a series of 1's in binary. Thus the bitwise complement operator (~), which flips all the bits, will result in a zero value for only -1.

Okay..Sure..Why not?

Everything will be fine, right? No nightmares of evil javascript code coming to get you in your dreams and such? No.


> [1, 10, 2, 1400].sort() 

[1, 10, 1400, 2]

Yes, that second line is the output of the sort. From the docs:

…elements are sorted by converting them to strings and comparing strings in Unicode code point order

Provided you don’t supply a custom comparator.

The right code?

> [1, 10, 2, 1400].sort(function(a, b) { return a-b; } );

[1, 2, 10, 1400]

Imagine you’re writing an algorithm that uses sort. Some test cases pass, others don’t, and you start digging in to your code only to find that it isn’t actually sorted?

Yeah well I guess you should just RTFM, right? Yeah, that’ll solve all your problems.

Non-Object This

function getThing() {
return obj[this];

Okay..so it’s a function that accesses object using…this? So I’m accessing an object, with an object, right?

Then you discover ‘this’, is a string. WHAT?

The assumption in this function is that the caller did something like this:

var getSpecificThing = getThing.bind(‘propertyOfObj’);

Now we have an object with a string as its context, right(bind docs here)?

Not quite.

> function getThing() {
> // () to call function immediately
> getThing.bind('propertyOfObj')()
String {0: “p”, 1: “r”, 2: “o”, 3: “p”, 4: “e”, 5: “r”, 6: “t”, 7: “y”, 8: “O”, 9: “f”, 10: “O”, 11: “b”, 12: “j”, length: 13, [[PrimitiveValue]]: “propertyOfObj”}

What have we done?

It turns out, what we have here is a string which has had toObject called on it. If you ‘use strict’ in getThing, however, this ‘feature’ goes away.

> function getThing() {
'use strict'
> // () to call function immediately
> getThing.bind('propertyOfObj')()

We just get a string, which seems to make some amount of sense. If we do decide to give a string as our ‘this’ (though I would hope you don’t), it is less surprising to have it indeed be a string when we use it. This still does nothing to prevent the sheer terror you potentially inflict on another innocent developer (or intern) who happens to come across a string ‘this’.

Var Hoisting

> function a() {
x = 1;
var x;
> a();

You would probably expect ‘x’ to be undefined, yet this code is equivalent to this:

> function a() {
var x;
x = 1;
> a();

From the docs

declaring a variable anywhere in the code is equivalent to declaring it at the top. This also means that a variable can appear to be used before it’s declared. This behavior is called “hoisting”

Writing code that relies on this behavior should be considered cruel and unusual punishment for those who must later decipher it.

Defensive Semicolon

;(function(window) {

What is that semicolon doing, you might ask? Well imagine a scenario like the one below, except the first line is code that got concatenated with yours (which is the second line).

From wikipedia:

a = b + c
(d + e).foo()

// Treated as:
// a = b + c(d + e).foo();

If the author of some other script forgot, or simply opted not to include a semicolon at the end, it might treat your library code as part of an expression in the preceding script.

Javascript is a strange and terrifying language

So if you ever wondered why there are projects to compile every other language to JS, this might get you started. In addition, check out Gary Bernhardt’s video (embedded above) for things like this:

To learn why this actually happens, go here

In fact, there’s a tool out there that turns any JS code into this form:

A tool and javascript library for converting strings, numbers, and scripts to equivalent sequences of ()[]{}+! characters that run in the browser.

Is there hope?

Maybe. ES2015/ES6 is quite promising in many ways, yet for all that it may help, it will also enable you to do things like this:

> let obj = { a: [{ foo: 123, bar: ‘abc’ }, {}], b: true };
> let { a: [{foo: f}] } = obj;
> f

I didn’t come up with this example, and I don’t know how it works. I’ve been told it’s nested destructuring. Is it often useful? Probably. Will people write code that looks like this example? Yes.

In addition, the arrow function syntax (usefully) provides a difference over the current syntax, preventing you from needing to bind functions to this in callbacks.

While this feature is useful to those who are aware of it, it is just one more obscure detail of the language to those who don’t, no matter how much I enjoy the new syntax myself.

What’s the difference between a language like Javascript, and a language like Python (aka “executable pseudocode”)?

Javascript has to maintain compatibility with past versions. If you need proof of this, look no further than typeof null. This is a scenario in which a bug in the very first version of Javascript has been persisted solely due to the fact that it has existed for too long.

So if you ask me, no. There is no hope.

This post also appears on Behance’s blog and my personal website.

Follow me on twitter! @NickArthur5

Like what you read? Give Nick Arthur plays Life a round of applause.

From a quick cheer to a standing ovation, clap to show how much you enjoyed this story.