Why JavaScript is actually a great LeetCode/Interview language
Tags: javascript, leetcode, interview, hackerrank
Published: 2020-09-18 06:26:24

# **In reality, the best language is the one you're comfortable with.**

But if you're debating learning a non-strictly typed language, or stuck between several choices, I want to present a couple of reasons why JS might be worth a try.

## Everyone is on the [LeetCode](https://leetcode.com/) grind these days.
If you're unfamiliar with LeetCode, it's a way to practice interview-type coding challenges in a short time frame. This article applies to actual interview services too, whether that's HackerRank, CodeSignal, HireVue, or any of the other numerous testing services.



For beginners, it's often parroted that **Python, Java and C++** are the "big 3" to learn for LeetCode. 

It's often said that C++/Java are great choices because they're super fast, have wide standard libraries, and strictly typed. C++ has a bit more convolution with memory management and iterators, but trades that for speed. Java is notoriously verbose, which is often against the spirit of fast iteration during interviews.

On the other hand, people often like Python since it's similar to writing pseudocode, it has a super beginner friendly community, and is fast to iterate upon.

I'm going to present some reasons (in no particular order) why JavaScript might be the best of both worlds for coding challenges (but especially as an alternative to Python). 

**I'm going to avoid dissing other languages in my reasoning, because I'm not quite as familiar and wouldn't want to misspeak about features.**



# #1) - Everything is objects (and that's awesome)
```javascript
const object = {"key": "value"}

object.key // 'value' -- O(1) access/insertion time obv.
object.newKey = 'newValue'
object['key'] == object.key // true
// Easy to iterate (and it has fixed ordering)
Object.entries(object) // [ [ 'key', 'value' ], ... ]
``` 
Objects are awesome, flexible, and arguably the most important data association in software development. 

I'd argue that "HashMap" type data structures are more valuable and more widely used than arrays. Fun fact: In JS `typeof([1]) // 'object'` -- even arrays are objects, just with some special additional properties. 

But essentially we can use them as replacements to Sets/Maps/Dictionaries in other languages (which I'm sure a crazy high percentage of LeetCode-type problems require). And for problems that need to maintain insertion order we can use `Map()` and `Set()` in JS.

We can also easily use objects to represent Linked Lists, Trees, Graphs, Tries and more! This is essential when problems require to build out more complex algorithms. 
```javascript
let graph = {
'1': {
   edges: [2,4,5]
},
'2': {
   edges: [...]
}
....
}

let trie = { 
a: {
   b: { c: {} },
   d: {}
}
```

# #2) Sometimes strict, static typing is awesome (but not for speed)
```javascript
> [] + []
''
> {} + []
0
> [] + {}
'[object Object]'
// wtf https://www.destroyallsoftware.com/talks/wat
```

For real maintainable, testable, reliable code, it's almost always to have some typing assistance, whether that's a bit lighter (TypeScript) or super heavy (Rust).

But oftentimes that comes with the trade-off of fast iteration (or writing nothing but `auto`). 

Learning how type coercion and non-static typing works in JS and similar scripting languages (Python, Ruby) makes it super easy to do fast tricks. 

Essentially our JS engine does a best-effort type coercion when we're comparing or operating different types (eg. Number, String, Object, Array) -- that can give us some initially strange side effects. But let's show an example of how we can use this to our advantage!
```javascript
// Do a frequency count on an array 'a'
// and store it in a object 'o' {key: count}
const o = {}
a.forEach(e => { o[e] = o[e] + 1 || 1 } )
// if o[e] doesn't exist, it's 'falsy'
// we short-circuit logical OR to return 1
```
I use this code basically all the time -- but there's plenty of other instances where this type coersion (especially knowing 0, '', null, undefined are all fasly values).

# Reason #3) JSON = JavaScript Object Notation (and the web <3s it)
This advantage applies less to LeetCode problems, but more to take-home assessments. Build a small app to hit and API and do some data manipulation and POST it back to another endpoint.

This is what JS was built for, manipulating and handling data between web services. Almost every API or take-home assessment will involve JSON in some way or another -- and  the built-in methods like `JSON.stringify()` and `JSON.parse()` make it a breeze.

From personal experience, I've done assessments with **HubSpot** and many others -- their whole focus is on real-world work for their assessment -- nothing is more real-world then GET requests and parsing JSON.

I was able to work extremely fast through the problems because I don't have to think twice about setting up libraries or schemas -- I just use Axios/Node-fetch and get back a fully usable object that I can manipulate to my heart's content.

And even for testing, being able to just paste JSON into an IDE and it immediately being a valid object to work with is extremely valuable.

# #4) Built in array methods make life easy

Array questions are just about the most common input data structure, so you'll be manipulating and iterating through them often.

I'll just quickly enumerate some awesome array methods that I find myself using all the time in LeetCode and interviews (interviewers are often impressed by how quick and easy it makes certain problems).

### Basic data manipulation (we can reduce mental complexity and use arrays as stacks and queues in JS) 
1) [pop()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/pop)
```javascript
['1','2'].pop() // a = ['1'], returns '2'
```
2) [push()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/push)
```javascript
['1'].push('2') // a = ['1','2']
```
3) [shift()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/shift)
```javascript
['1','2'].shift() // a = ['2'], returns '1'
```
4) [unshift()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/unshift)
```javascript
['2'].unshift('1') // a = ['1','2']
```
5) [slice()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/slice)
```javascript
[1,2,3].slice(1,2) // a = [2, 3]
// selects from index start -> end (optional) -- negative start index works too
```
### Some iterative array manipulation (by order of most useful)
1) [forEach()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/forEach) 
```javascript
a.forEach((e,i) => console.log(e, i)) // [1,2,3] -> prints 1 0 2 1 3 2
// iterates through each element
```
2) [map()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map) 
```javascript
a.map(e => e+1) // [1,2,3] -> [2,3,4]
// returns a new array with per element manipulation
```
3) [reduce()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reduce)
```javascript
a.reduce((accum,e) => accum += e, 0) // [1,2,3] -> 6
// returns value that results from the reduction
```
4) [sort()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort) 
```javascript
a.sort((a,b) => b-a) // [1,2,3] -> [3,2,1] 
// returns a new array sorted based on the call-back comparison
```
5) [filter()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter) 
```javascript
a.filter(e => e%2!==0) // [1,2,3] -> [1,3] 
// returns a new array based on elements where the return is truthy
```

### Extras
1) Turning strings into arrays and vice-versa (super common)
```javascript
> "string".split('')
[ 's', 't', 'r', 'i', 'n', 'g' ]
> [ 's', 't', 'r', 'i', 'n', 'g' ].join(' ')
's t r i n g'
```
2) [reverse()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/reverse)
```javascript
[1, 2, 3].reverse() -> returns [3,2,1]
```
3) [every()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/every)
```javascript
a.every(e => e > 0) // [1,2,3] -> true
// [-1, 2, 3] -> false 
// returns true if every element evaluates to true for the expression
```
4) [some()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/some)
```javascript
a.some(e => e > 4) // [1,2,3] -> false 
// returns true if any element evaluates true for the expression
```

Read about every array method [here](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array)

# #5) JavaScript execution ([V8](https://v8.dev/)) is ridiculously quick

Language specific time-outs are supposed to be adjusted to fit the execution model. But I've heard on the internet and from friends, sometimes you'll hit the optimal solution in HackerRank, but still get TLE (time limit exceeded) timeouts for larger test cases in Python. 

Worry no longer about execution on larger datasets -- you'll be competing speed-wise with C++ and Java when you use JavaScript (where the V8 JavaScript engine reigns supreme (Chrome, Node.js)). 

Essentially if you're able to get an optimal solution, or even something close to it, you'll get through all hidden test cases from a timing perspective. 

[JS vs Python](https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/python.html)
[JS vs C++](https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/node-gpp.html)
[JS vs Java](https://benchmarksgame-team.pages.debian.net/benchmarksgame/fastest/javascript.html)

# Misc advantages:
These don't necessarily fit neatly in a category, but I felt it was important to bring up these positives.

1) [Object destructuring](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment)`const { result } = { result: "answer" }`
2) [Optional chaining](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Optional_chaining) `animal?.color?.hexcode`
3) [NPM](https://www.npmjs.com/)/Yarn -- package.json and large access to libraries for take-home assessments, make package managment a breeze
4) [Spread operator](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Spread_syntax) `Math.max(...a)` 

# A few downfalls or dislikes:
1) Lack of heap structure (at least built-in)
2) Direct string  manipulation feels hacky: charAt(), split(), splice()
3) Array slicing feels less clean than Python implementations.

Thanks for reading! Let me know if you have any thoughts, why JS is great or not-great for coding interviews/LeetCode!