Foxy JavaScript
Tags: javascript, syntax, programming
Published: 2020-11-05 18:52:52

---
title: Foxy JavaScript
published: true
date: 2020-05-27 18:20:14 UTC
tags: javascript,syntax,programming
canonical_url: 
---

How to outfox some of the trickiest aspects of the language

![](https://cdn-images-1.medium.com/max/1024/1*-kIJ2nSl6dwz0bQ0O-K01A.png)<figcaption>Photo by Alex Andrews from <a href="https://www.pexels.com/photo/photo-of-fox-sitting-on-ground-2295744/">Pexels</a></figcaption>

It’s common knowledge that JavaScript is a highly nuanced, fast and loose programming language that can result in some head shaking results.

Based on my journey into the language so far, this is what I’ve observed are the **Top 10 Slyest Quirks of JavaScript.**

**#1 Implicit Coercion**

Notably, this quirk is one of the most infamous parts of the language. To oversimplify, implicit coercion is JavaScript’s ability (or deranged propensity?) to coerce one value type to another type. Some would argue that the value is coerced to the _expected_ type. We get these fun little nuggets as a result of implicit coercion:

```javascript
1 < 2 < 3; // --> true 

// but...   

3 > 2 > 1; // --> false

9 + '1' // --> '91'

// but...

91 - '1' // --> 90
```

It gets even odder when working with arrays:

```javascript
[] == ![]; // --> true

true == []; // --> false
true == ![]; // --> false

false == []; // --> true
false == ![]; // --> true
```

Head-scratching for sure. There’s actually some interesting logic behind these coercions (based on the operation being performed and the operand types that are involved), but it’s pretty opaque to someone new to the language. If you get some surprising results, be on the lookout for this (and better yet, test any questionable operations being performed in your handy REPL). Also, get in the habit of using the strict equality operator `===` when comparing values or checking a variable’s type with the typeof keyword.

**#2 Semicolons**

This is a touchy subject, but for the beginner programmer, it’s more than an annoyance. It’s difficult to know when _not_ using them will cause your code to implode. So, we’ve had the fear of God scared into us, and we just add them religiously. Point taken.

Take a look at this example:

```javascript
let students = ''

['Sam', 'Ari', 'Sharon', 'Steve'].forEach((name) => {

    if (name !== 'Steve') {
      name += ' & ';
    }

    students += name;

});

console.log(students);

// expected: 'Sam & Ari & Sharon & Steve'
```

Instead of the expected output of a string with alternating names and ampersands, it throws the error “_Cannot read property ‘forEach’ of undefined_.” Because a semicolon is missing from the end of the first line, the code is not parsed correctly, and the first line essentially bleeds into the second line:

```javascript
let students = ''['Sam', ...].forEach(...)
```

To avoid this issue, you need get in the habit of terminating every statement with a semicolon. Period. (Or, I guess, semicolon?)

**#3 Elusive Return Values**

“_Question_: What does this function return?”

“Answer: A new array? Itself, just mutated? The length of the array? Undefined?”

Some methods, such as `Array.prototype.map()` and `Array.prototype.filter()` return a brand new array of elements with the intended changes implemented in the new array. Great! Just as we expected.

Other methods, such as `Array.prototype.sort()` and `Array.prototype.reverse()` mutate and then return the original array. As a n00b, how do you know exactly what a method will return? Well, there’s no easy way to know what a method will return unless you commit it to memory or look it up (or test it in your REPL). Honestly, it has more to do with _when_ the methods were added to the language than the underpinnings of the methods themselves, but a little consistency would be a welcome relief to someone new to the language. </gripe>

**#4 `Array.prototype.forEach()` and `Array.prototype.reduce()`**

You know that awkward moment when you bring something up at a party that makes everyone in a previously chatty group go quiet? Say something strongly worded about either of these methods at a local JS Meetup, and you’ll know what I mean.

This is an interesting dilemma, and it might be too early for a developer to pick a side if they’re just getting their feet wet. Some argue that `forEach` is problematic because it primarily relies on side effects to get the job done. Case in point, it’s important to note (and commit to memory) that `forEach` always returns… undefined (surprise!) and not itself, so you can’t chain it like many other array methods. This may come back to bite you at some point. From a best practices standpoint, other methods that don’t depend on side effects (e.g., changes in state that don’t depend directly on the function inputs), are easier to read and predict because they have clear semantic meaning. In this case, less is more.

```javascript
let newArr = [];

[1, 2, 3].forEach((element) => {
  if(element > 1) {
    newArr.push(element);
  }
});

console.log(newArr); // [2, 3]
```

Compare this to the same task using `Array.prototype.filter()`:

```javascript
let newArr = [1, 2, 3].filter((element) => element > 1);

console.log(newArr); // [2, 3]
```

`Array.prototype.reduce()` is an interesting, and powerful method, but some would argue that it makes the code more difficult to parse (for humans). It essentially “reduces” an array down to a single output value. This can make calculating a sum or removing duplicates from an array very streamlined, but it comes at the expense of less readable code. I think it’s valuable to become familiar with the method, but keep the pros and cons in mind.

**#5 Spread Operators (AKA “…”)**

This is the perfect syntax to use if you want to build anticipation...

All joking aside, the spread operator is useful, but it’s not super clear when it should be used. MDN states:

> **Spread syntax** allows an iterable such as an array expression or string to be expanded in places where zero or more arguments (for function calls) or elements (for array literals) are expected, or an object expression to be expanded in places where zero or more key-value pairs (for object literals) are expected.

The spread operator performs differently in different contexts. Here are just a few situations where you’ll find the spread syntax useful.

- It effectively “spreads” an array (or more than one array) into separate arguments when used in a function call. For example, when calling `Math.max()` or `Math.min()`:

```javascript
let arr = [1, 3, 2, 0];

Math.max(...arr); // 3
```

- With more than one array:

```javascript
let arr1 = [-1, -2, -3, -4];
let arr2 = [10, 3, -8, 1, 9];

Math.max(...arr1, ...arr2) ); // 10
```

- Or it can be used to easily copy an array:

```javascript
let arr = [1, 2, 3];

let newArr = [...arr];

console.log(newArr); // [1, 2, 3]

arr === newArr; // false
```

- It can also be used to expeditiously split a string into an array:

```javascript
let string = "Hello!";

console.log( [...string] ); // ['H', 'e', 'l', 'l', 'o', '!']
```

It’s important to distinguish the _spread operator_ from a different construct, _rest parameters_, since they both use the same syntax of "..." .

- Rest parameters are used in functions to allow them to accept any number of arguments. You can spot rest parameters when they’re used at the end of function parameters when a function is declared.
- Spread syntax is used when passing in an array (or multiple arrays) during a function call.

**#6 Implied Globals**

New programmers are continually warned not to “pollute the global scope,” but what exactly does that mean and how does the concept of implied globals play into that? When variables or functions are inadvertently named the same thing in the global scope, we refer to the problem that causes as _name collision_. This can happen when multiple teams are contributing code to the same project. Projects are prone to name collision if too many variables and functions are added to the global namespace, also referred to “polluting the global scope.”

To make matters worse, you can very easily add variables to the global scope unintentionally due to the occurrence of _implied globals_. Basically, if you don’t follow best practices and forget to explicitly declare your variable, it is interpreted by the language that you _meant_ to declare it as a global variable:

You type:

```javascript
sum = 10;
```

JS interprets that as:

```javascript
const sum = 0;
```

Or another example (of chaining variable assignments):

```javascript
const findSum = (a, b) => {

  let sum = total = a + b; 

};
```

In this example, `sum` is scoped as a local variable, whereas `total` is scoped as a global variable. Oops.

Word to the wise: define each variable explicitly and keep your global scope tidy.

**#7 Double NOTs**

Despite there being a perfectly acceptable and _readable_ built-in Boolean function (which casts most anything to a boolean), the double not, or `!!` is clear as mud. It also forces a value to a boolean:

```javascript
!!0 
!!null
!!undefined

...all return the boolean false. Nifty.
```

Here’s a joke that helps explain it:

> A linguistics professor once said “A double negative forms a positive, while in some languages, a double negative is still a negative. However, there is no language wherein a double positive can form a negative.”

> A voice from the back of the room piped up, “Yeah, right.”

In a nutshell, the first ! converts the value into a boolean and it returns the inverse. The second ! will inverse _that_ boolean, and in this convoluted manner, it converts the value to a boolean.

Can’t hardly find no fault in that.

**#8 Variable Shadowing**

This quirk isn’t unique to JavaScript, but it will get new programmers every time. It’s taught that you should pick the most descriptive variable names as possible, but what if that leads you to use the same variable name to declare a variable in the global scope and again in the local scope? That’s when it gets messy. The locally scoped variable essentially shadows, or overrides the previously scope global variable. Here’s an example:

```javascript
let num = 3;

function example() {
    let num = 1;
    num += 10;
    return num;

}

console.log(num); // 3
```

Did you expect to see an output of 11? In variable shadowing, if you declare a variable by the same name in both the local and global scope, the local variable will take precedence when you use it within a function. Shadowing can make reading code confusing and it also makes it impossible to access the global variable from within the function scope. Linters often have a “no-shadow” rule for good reason. Beware of lurking variable shadowing.

**#9 Hoisting**

For me, this term always invokes the image of a horse in a gurney (Phish fans?). It doesn’t sound elegant, but it’s a powerful part of the JavaScript language: no matter where variables are declared within a particular scope (local or global), all variable declarations are moved to the top of their scope. Like something out of Inception, it means that variable declarations are always processed before any code is executed (only applies to the declaration, not the assignment).

Related to #8 above, this can catch some developers off guard. It can lead to behaviors that you weren’t expecting if you’re unaware of hoisting: rather than being available only after their declaration, variables and functions might be available beforehand in the code, which might have some unanticipated consequences (both positive and negative).

For this reason, it’s advisable to get in the habit of declaring all variables at the top of their scope (for global scope or at the top of the local function scope).

**#10 Using `typeof` on null results in “object”**

smh…

Honestly, this is just accepted as a bug in the language, but if you’re curious about the history of it, you can find out more [here](https://bitsofco.de/javascript-typeof/).

* * *