Unravelling JavaScript: Commonly Misunderstood Methods and Features

Hero image for Unravelling JavaScript: Commonly Misunderstood Methods and Features. Image by Lysander Yuen.
Hero image for 'Unravelling JavaScript: Commonly Misunderstood Methods and Features.' Image by Lysander Yuen.

JavaScript is not just a programming language; it's a canvas of possibilities, rich with features that make it both incredibly powerful and at times totally bewildering. It is common to find even seasoned developers tripping up over some of it's more quirky idiosyncrasies.

Today, I'm going to explore some of the most commonly misunderstood aspects of JavaScript and in an attempt to find some more relevant and interesting content for my blog and website visitors over the coming weeks and months, I'll put together a short article to focus on each in more detail.

For now, here's a list of some of the aspects of JavaScript that are most commonly misunderstood or have gotchas that catch out even the most experienced of developers:


Array.prototype.sort()

There's more than meets the eye with sort(). Have you ever tried to sort an array of numbers and ended up with 10 before 2? That's sort() in action, treating elements like strings.

I go into more detail on understanding Array.prototype.sort() here, and into even deeper detail on how you can use sort() to sort arrays of objects (like sorting products by prices) here.


Array.prototype.slice()

Using slice() silently duplicates sections of your array without altering the original. It is really common to see this mistaken with its more invasive counterpart, splice(), which behaves quite, quite differently...

I talk about using slice() in detail here.


Array.prototype.splice()

splice() is a bit of a multitool for arrays, capable of adding, removing, and replacing elements. Its versatility can be daunting and easily misunderstood, making it prone to misuse.

Read more about manipulating arrays with splice() here. I go into even more detail comparing slice() against splice() in my article here.


String.prototype.substring()

Extracting parts of a string should be simple, and substring() is just the tool for the job. It extracts characters from a string (just as you'd expect), but unlike its relative slice(), it has some confusing peculiarities when it comes to dealing with negative or outoforder arguments.


String.prototype.substr()

Although substr() has been depreciated for quite some time (and in fact never made it into the JavaScript core specification), it still crops up on legacy codebases, and gets introduced anew by developers confusing it with substring(). Despite being virtually identical on the surface, substr uses length for extraction instead of the ending index, which makes it just dissimilar enough to cause confusion.

I talk about substring() and substr(), comparing the two in my article here.


String.prototype.split()

split() should be simple: give it a string and should return that same string in an array, broken down based on a predefined delimiter. However, understanding how different delimiters, or their absence, affect the output makes it more complicated than you might expect.

I've written an article all about manipulating string with split() here.


Math.random()

I've written about Math.random() before, and how actually you cannot create a truly random value using maths. Nevertheless, Math.random() is a pseudorandom number generator that can mislead those expecting numbers outside of the 0to1 range.


parseInt()

Turning strings into integers with parseInt() can lead to some unusual and unexpected results if you ignore the radix. How it behaves with unexpected characters in the string can also result in hardtofind bugs.

I've written about parseInt and the importance of understanding radix here.


isNaN()

The isNaN() function checks if a value is NaN ("Not a Number"), but it can return true for unexpected inputs, making it unreliable without understanding its coercion rules. I go into this in much more detail in a previous article here.


typeof

It may seem like typeof is a straightforward gatekeeper for type checking but can often output types that aren't accurate, particularly when it comes to arrays and null.

I have written about typeof, how it can be used and where it becomes more limited here.


instanceof

instanceof checks the prototype chain for a constructor but can quickly lead to false negatives, especially when dealing with multiple contexts, such as different iframes or realms.

You can read about instanceof and it's uses in detail in my article here.


null and undefined

Both null and undefined represent "no value", but they have different meanings and uses. They are not interchangeable, especially in comparisons.

This is something I've written about before.


== and ===

The equality (==) and strict equality (===) operators are similar at a glance, but understanding their coercion rules is vital to prevent unexpected type conversions. I've written about the differences between these equality operators and their uses before.


Object.prototype.hasOwnProperty()

hasOwnProperty() checks for a property's existence directly on an object, not on its prototype chain. This distinction is easy to overlook and can lead to incorrect assumptions about an object's properties.

Read a brief overview of hasOwnProperty in my article here.


Function.prototype.apply()

apply() calls a function with a given this and arguments provided as an array. It can be intricate to master, especially when dealing with the arguments arraylike object.

I go into detail about .apply() in my article here.


Function.prototype.bind()

Like apply(), bind() creates a new function with a set this and arguments. It can tie a function's this value and arguments for later use. This can sometimes be conflated with apply() and call(), which are immediate invocations.

You can read about .bind() in my article here.


setTimeout()

Any JavaScript developer should know, setTimeout() schedules code to run after a defined delay. However, its timing can be imprecise due to JavaScript's singlethreaded nature and event loop.

I have written about using setTimeout and the potential issues with timing accuracy here.


setInterval()

On a similar vein to setTimeout(), setInterval() is a handy way to run code at regular intervals, however, it can quickly result in queued calls if its callbacks take longer than the interval time.

Read more about setInterval in my article here.


Object.defineProperty()

defineProperty() configures properties with fine granularity, including descriptors like writable and enumerable. However, the complexity of these attributes often leads to misuse.

I talk about harnessing this powerful JavaScript method here.


Promise.prototype.then()

The then() method is the backbone of promise chaining, yet it is often misunderstood because it is used to handle the success or failure of a promise, whilst it returns a new promise that can itself be chained to other promises. It can get very confusing.

I have written about leveraging then() in modern JavaScript here.


Categories:

  1. Development
  2. ES6
  3. Front‑End Development
  4. JavaScript
  5. React