Category Archives: JavaScript

PHP in_array or array_search vs JavaScript includes or indexOf

In my previous post, I’d created a bug in my PHP code by improper use of PHP’s array_search function. If you only write PHP, this kind of thing will probably never happen to you. I also write Java and JavaScript code, and at some point, your memory banks overflow, and you forget stuff!

JavaScript has a couple of different methods for searching through an array to find an item. Let’s use the array method includes to search for an item in JavaScript, just like I did in my PHP example.

var foods = new Array();
foods.push('ice cream');
foods.push('hamburger');
foods.push('brussels sprouts');

var do_important_things = function() { console.log('Important!'); };

if (foods.includes('ice cream')) {
    do_important_things();
}
...

If you print out foods, you can verify that ‘ice cream’ is located at index 0. The code foods.includes('ice cream') returns true because that string is found in the array. No confusion there – a boolean is returned, not an index.

If I’m doing a more complicated comparison, I might use JavaScript’s some, like this:

if (foods.some(function(el) { return el.toLowerCase() === 'ice cream'; })) {
    do_important_things();
}

The some method loops over all elements in the array until the callback method returns true, at which point it stops, and returns true. If no item is found which satisfies the condition in the callback, then false is returned. Again, since a boolean is returned and not an index, there’s no room for error.

There’s a JavaScript method which is the equivalent of the PHP array_search function: indexOf. It returns the index of the matching item, if found, and otherwise returns -1. Here’s an example:

if (foods.indexOf('ice cream')) {
    do_important_things();
}

Oops, this method of searching exhibits the same bug as array_search in PHP! In my opinion, the indexOf JavaScript method is more appropriately named – it makes it clear that you are going to get an index as a return value. So it makes it less likely that the all-too-human developer will create the bug that I demonstrated in my previous post.

Now, when researching this topic, I found that PHP has a function that is more appropriate than array_search for my use case. It’s the in_array function. It returns TRUE if the item being sought is found in the input array. That’s really what I wanted! Here’s the example code that I used in my previous post, only now it uses in_array:

$foods = Array();
$foods[] = 'ice cream';
$foods[] = 'hamburger';
$foods[] = 'brussels sprouts';

function do_important_things() {
    echo 'Important!';
};

if (in_array('ice cream', $foods)) {
    do_important_things();
}

In this example, do_important_things is called.

If you found this interesting, click the subscribe button below! I write a new post about once a week.

About those JavaScript performance tests

In my last couple of articles, I wrote about some simple performance tests to compare Array.some with a for loop. I noticed that the for loop ran substantially faster the second time it was called in my process, while Array.some did not.

This got me curious. I wanted to know what was happening, so I dug around a little bit. It’s the kind of behavior that can be pretty tough to track down. I started with freenode for #Node.js. I described what I’d seen and got some feedback. I didn’t find a definitive answer, although I did get a clue. I was told essentially that “microbenchmarking” is pointless, and one should just write maintainable code, and let the JIT compiler worry about performance. I was directed to Mr Aleph‘s website. Mr Aleph is a compiler engineer and enthusiast, and I found a lot of interesting articles at his site.

In 2012 already, he had written a microbenchmarks fairy tale. It turns out that the V8 JavaScript engine compiler performs various optimizations that can produce misleading benchmarks. As an example, he talks about LICM (“loop-invariant code motion”). Oh god, the jargon! But he gives an example, which I’ll explain now.

Prior to working with JavaScript, I was a Java coder. In Java, one commonly writes for loops like this: for (int i = 0; i < arr.length; i++) {...}.

When I was getting started using JavaScript, I was told to assign Array.length to a variable outside the loop, and then reference the variable in the iteration, like this:

var len = arr.length;
for (var i = 0; i < len; i++) {
    ...
}

The reason given was that JavaScript is an interpreted language, and it will evaluate Array.length on every iteration over the loop! Sounds wasteful to me. So I’ve been dutifully, manually setting a variable to Array.length outside my loop ever since then.

Java developers don’t need to do this, because Java is a compiled language. The compiler performs optimizations behind the scenes which basically do what I was doing manually in JavaScript.

Flash forward to 2008-ish, about 10 years ago, when Google Chrome was launched, integrated with the V8 engine. If you thought I’d gotten off-track, I’m now back on it. According to Mr. Aleph, the V8 engine uses LICM, and LICM performs the optimization I’ve been doing manually in assigning Array.length to a variable outside the loop. And that’s just the tip of the optimization iceberg.

If you want to read more about the V8 engine, there’s an excellent series about it written by Alexander Zlatkov in 2017. Start with How JavaScript works: inside the V8 engine + 5 tips on how to write optimized code. You should also take a good look at Mr. Aleph‘s articles.

Once JavaScript is not strictly being interpreted, trying to benchmark and optimize your code manually is probably just a mistake. Mr. Aleph’s conclusion, in 2012, was

The time when you could have easily guessed the cost of a single operation by simple observation is over. If you want to know something then sometimes the only way is to go and actually learn it from the inside out.

Mr. Aleph, “microbenchmarks fairy tale“, 2012

My own conclusion is that you should not think you are going to outsmart an optimizing compiler. Just write code which is readable. If, at some point, you notice bottlenecks, that’s when it makes sense to dig for performance improvements.

But I’ll still move Array.length outside of my iterators 😉

If you found this interesting, click the subscribe button below! I write a new post about once a week.

A performance test of the JavaScript Array.some function in Chrome browser

Previously, I performance-tested the Array.some function in Node.js version 8.16. Node.js is usually used for running microservices as a backend on a server. It’s not identical to JavaScript running client-side, in the browser. So it’s also interesting to run the same kind of performance test in a browser to see if the results apply there, too.

The source code for this test is similar to what it was in my previous test using Node.js. There are some necessary differences. I wanted to use the same word list, but I didn’t want to fiddle with trying to get the browser to read from a file, which is complex at best and impossible at worst (for security reasons).

Instead, I decided to use XMLHttpRequest to grab the word list I’d used previously, which was handily available on a web page.

However, you can’t just open Chrome browser and run the code below. If you try it (and you might want to), you’ll see this error message:

Access to XMLHttpRequest at 'https://norvig.com/ngrams/count_1w100k.txt' from origin 'chrome-search://local-ntp' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

Oops! The solution is to first surf to Norvig’s page, then open the JavaScript console with Ctrl-Shift-J, paste in the code below, and call runTest().

/* Displays results */
var finishAndPrint = function(words) {
    console.log("words length: " + words.length);
    console.log("First word: " + words[0]);
    console.log("Last word: " + words[words.length-1]);
};

/* This test function is guaranteed to never match a word in the Norvig list of words */
var testFunction = function(item) {
    return item === "gsdjkoeu";
};

/* A performance test using the Array.some method: */
var performanceTestSome = function(words) {
    let t0 = performance.now();
    let result = words.some(function(el, i) {
        return testFunction(el);
    });
    let t1 = performance.now();
    console.log("The some method took " + (t1 - t0) + " milliseconds and the result was " + result + ".");
};

/* A performance test using a simple for loop: */
var performanceTestForLoop = function(words) {
    let len = words.length;
    var result = false;
    let t0 = performance.now();
    for (var i = 0; i < len; i++) {
        if (testFunction(words[i])) {
            // This code is necessary so the function does the same thing as the "some" method
            result = true;
            break;
        }
    }
    let t1 = performance.now();
    console.log("The for loop method took " + (t1 - t0) + " milliseconds and the result was " + result + ".");
};

/* Read words from a URL and return the list of words */
var readTheWordsFromURL = function() {
    let myURL = "https://norvig.com/ngrams/count_1w100k.txt";
    var xmlHttp = null;
    xmlHttp = new XMLHttpRequest();
    xmlHttp.open( "GET", myURL, false );
    xmlHttp.send( null );
    return xmlHttp.responseText;
};

var runTest = function() {
    var data = readTheWordsFromURL();
    var words = [];
    var lines = data.split('\n');
    lines.forEach(function(row, i) {
        var items = row.split('\t');
        if (items[0].length > 0) {
            words.push(items[0]);
        }
    });
    finishAndPrint(words);
    performanceTestForLoop(words);
    performanceTestForLoop(words);
    performanceTestSome(words);
    performanceTestSome(words);
};

runTest();

I did this in Chrome browser Version 75.0.3770.90 (Official Build) (64-bit), on my Ubuntu 16.04 desktop. I used private mode to make sure no other tabs, plugins, etc. would interfere with the test.

These were the results the first time I ran the code:

words length: 100000
VM18:4 First word: THE
VM18:5 Last word: PGY
VM18:36 The for loop method took 2.8300000121816993 milliseconds and the result was false.
VM18:36 The for loop method took 0.5550000059884042 milliseconds and the result was false.
VM18:20 The some method took 3.064999997150153 milliseconds and the result was false.
VM18:20 The some method took 2.6000000070780516 milliseconds and the result was false.

I repeated the test (closed the browser, reopened it, and ran the test), but this time changed the order of the tests. I ran the some test first:

...
VM18:20 The some method took 3.5149999894201756 milliseconds and the result was false.
VM18:20 The some method took 2.5599999935366213 milliseconds and the result was false.
VM18:36 The for loop method took 2.599999977974221 milliseconds and the result was false.
VM18:36 The for loop method took 0.670000008540228 milliseconds and the result was false.

Huh! I tried it again:

...
VM18:20 The some method took 3.5499999939929694 milliseconds and the result was false.
VM18:20 The some method took 2.634999982547015 milliseconds and the result was false.
VM18:36 The for loop method took 2.449999999953434 milliseconds and the result was false.
VM18:36 The for loop method took 0.5299999902490526 milliseconds and the result was false.

And again:

...
VM18:36 The for loop method took 2.9750000103376806 milliseconds and the result was false.
VM18:36 The for loop method took 0.5549999768845737 milliseconds and the result was false.
VM18:20 The some method took 3.939999995054677 milliseconds and the result was false.
VM18:20 The some method took 2.789999998640269 milliseconds and the result was false.

I ran another test case, just running the some method only. The result took 3.429999982472509 milliseconds. A test with just the for loop running once took 2.905000001192093 milliseconds.

The only conclusion I can draw is that Chrome doesn’t quite perform as well when running some instead of a simple for loop. The difference is not huge, and there’s some variation. This test runs over 100K words, and it still only takes a few milliseconds either way.

The results are similar to those in my previous post, which described a similar performance test using Node.js. This comes as no surprise, because Node.js runs on V8.

On the first run, it looks like a for loop performs a bit better than the some method. There’s some optimization on the second run. This is all déjà vu, if you read my last post.

Is it worth using a for loop everywhere to take advantage of that optimization? I think you’d really want to go deeper in your performance tests to understand the optimization, and make sure that it will be used before deciding to go with for loops everywhere. You will also want to be sure that it’s worth sacrificing code maintainability and readability in pursuit of some possibly minuscule performance boost.

It’s important to be aware of the potential for any performance impacts of special Array methods when architecting a new project or looking for bottlenecks in an existing one. But deciding never to use Array iterators just because you heard a vague rumor that they were not performant is unwise.

If you found this interesting, click the subscribe button below! I write a new post about once a week.

A performance test of the JavaScript Array.some function in Node.js

In my previous blog post, I talked about using the Array.some method as a handy tool for looping over “some” array elements until a condition is satisfied. Well, once in a while, you’re going to come across an article which is critical of “new-fangled” Array methods. It’s a known issue that some of these array methods perform poorly in comparison to the “old-fashioned” for loop.

It’s not that people don’t like the new methods. In the article mentioned above, Yotam Kadishay says they make JavaScript “more functional”, and writing code is “more fun and smooth” with the addition of these new methods. But if your code runs like a dog, no one is going to really care about how much fun you had writing it, will they?

Mr. Kadishay wrote a good article, and you should read it! He performance tested some of the newer Array methods, and found they tend to run slower than the older, tried and true ones. But he didn’t discuss the performance of the Array.some method. Array.some is actually not so new-fangled – it has been around since JavaScript 1.6 (2006).

So I’m going to performance test the implementation of Array.some, which is what I used in implementing my startsWithVowel method I wrote in my previous post. For test purposes, I’ve snagged Peter Norvig’s list of 100,000 words – they are all uppercase. I saved this list to my /tmp directory.

To be fair, I might want to run my performance test with a list of lowercased words, a mix of cases and so on. But for now let’s just work with this list.

I’m going to test this in Node.js. I use nvm (Node Version Manager) to use whichever version of node I’m interested in testing. I’ll test using node 8.16. I have node installed on a development environment running Ubuntu 16.04. To run my test, I fire up a node command line as follows:

nvm use 8.16
node
>

Then I just copy and paste the code below into the command line and look at the results:

/* Displays results */
var finishAndPrint = function(words) {
    console.log("words length: " + words.length);
    console.log("First word: " + words[0]);
    console.log("Last word: " + words[words.length-1]);
};

/* This test function is guaranteed to never match a word in the Norvig list of words */
var testFunction = function(item) {
    return item === "gsdjkoeu";
};

/* A performance test using the Array.some method: */
var performanceTestSome = function(words) {
    const {performance} = require('perf_hooks');
    let t0 = performance.now();
    let result = words.some(function(el, i) {
        return testFunction(el);
    });
    let t1 = performance.now();
    console.log("The some method took " + (t1 - t0) + " milliseconds and the result was " + result + ".");
};

/* A performance test using a simple for loop: */
var performanceTestForLoop = function(words) {
    const {performance} = require('perf_hooks');
    let len = words.length;
    var result = false;
    let t0 = performance.now();
    for (var i = 0; i < len; i++) {
        if (testFunction(words[i])) {
            // This code is necessary so the function does the same thing as the "some" method
            result = true;
            break;
        }
    }
    let t1 = performance.now();
    console.log("The for loop method took " + (t1 - t0) + " milliseconds and the result was " + result + ".");
};

/* Read the words: */
fs.readFile('/tmp/count_1w100k.txt', {encoding: 'utf-8'}, function(err, data) {
    var words = [];
    var lines = data.split('\n');
    lines.forEach(function(row, i) {
        var items = row.split('\t');
        if (items[0].length > 0) {
            words.push(items[0]);
        }
    });
    finishAndPrint(words);
    performanceTestSome(words);
    performanceTestForLoop(words);
    performanceTestForLoop(words);
    performanceTestSome(words);
});

Here’s the output:

> words length: 100000
> First word: THE
> Last word: PGY
> The some method took 2.5111299753189087 milliseconds and the result was false.
> The for loop method took 1.983236014842987 milliseconds and the result was false.
> The for loop method took 0.6664620041847229 milliseconds and the result was false.
> The some method took 1.9726130068302155 milliseconds and the result was false.

Huh, there’s some kind of optimization going on in that for loop. I didn’t investigate. I’m assuming the first run is more accurate. It looks like the for loop is slightly more performant than the some method.

I repeated the test in a couple of different ways, because I wanted to make sure that the order of calling didn’t matter. In each case, I exited the node command line using .exit and restarted it. Here’s another example output, in which I called the for loop method twice followed by the some test. In this case, it looks as if the performance difference is negligible on the first run of each method. However, it continues to appear that there’s some optimization which is done when the for loop method is used the second time, but not when some is used.

> words length: 100000
> First word: THE
> Last word: PGY
> The for loop method took 2.146267980337143 milliseconds and the result was false.
> The for loop method took 0.590969979763031 milliseconds and the result was false.
> The some method took 2.074671983718872 milliseconds and the result was false.
> The some method took 1.9943189918994904 milliseconds and the result was false.

Since I’ve got my code here and explained the methods I used, together with the environment, you can repeat the tests for yourself. I think it’s important to give as much information about your methods and environment when running performance tests. And if I were going to get more serious, I’d probably do some statistics, maybe run this test multiple times, and do a chi-squared test or some sort of test to make sure that my results are not a fluke.

Before you consider performance testing, think about whether performance will ever truly be an issue. Is it worth performance testing when you’re building a prototype for a startup and the code may never even get used by more than a few people? Is it worth sacrificing readability and maintainability in order to run the most performant code? Robert Harvey wrote this comment in response to a Stack Overflow question about performance testing Node.js:

you can have slow code run forever where a user won’t notice it, and pretty fast code running where they do, and they will complain about the pretty fast code not being fast enough. Or that your request to your server API took 220ms. Or something else like that. The point remains that if you take a profiler out and go looking for work to do, you will find it, but it may not be the work your users need.

It is probably true that performance is more important when writing server-side code. Your server’s going to be fielding a bunch of requests from multiple users; whereas the browser client is just dealing with “one user” at a time. Of course, you want good performance on the client side as well. You may want to play it safe and use for loops everywhere. That may be overkill 🙂 You’d still better know how Array methods work, and know how to read them, because there are plenty of developers and companies which are not nearly that strict about it.

In my next blog post, I’ll run the same test using JavaScript on the client.

If you found this interesting, click the subscribe button below! I write a new post about once a week.

How to check if a word starts with a value stored inside an array in JavaScript

Suppose you have an array of letters, and a word, and you need a little JavaScript code which answers the question: “Does this word start with any of the letters in my array?”. As an example, suppose the word is “aardvark” and your array is an array of vowels: [“a”, “e”, “i”, “o”, “u”]. At a glance, you can say that “aardvark” does start with the vowel “a”, so the answer to the question is yes.

Now you need to write the JavaScript code which will do the work for you, for any word at all.

First, you can use the fact that the JavaScript String type has a method startsWith which returns true if the string starts with the input value.

For example:

let value = "aardvark".startsWith("a");
console.log(value); // prints "true"

That’s a good start. Now we need to check all the vowels in our array. There’s a very handy Array method, some, which can be used for this purpose. Let’s look at how it works for this example:

let vowels = ["a", "e", "i", "o", "u"];
let value1 = vowels.some(function(vowel) {
    return "aardvark".startsWith(vowel);
});

The way this code works is that some evaluates the passed in callback function for every vowel in the array until it finds one which returns true (or more correctly, a “truthy” value). Then, it stops, and doesn’t look at any more vowels in the array – the output of the method is true. If the function never returns true – for example, if we replaced “aardvark” with “camel” – then the output of some would be false.

Let’s rework this code so that it can be easily reused for any word:

let startsWithVowel = function(word) {
    return vowels.some(function(vowel) {
        return word.startsWith(vowel);
    });
};

Then you can test this for any word you want. For example, open Chrome browser, open the JavaScript console by typing Ctrl+Shift+J, and type in the above code to define your function. Then you can test the function manually with different inputs, like this:

> startsWithVowel("aardvark");
true
> startsWithVowel("umbrella");
true
> startsWithVowel("camel");
false

The cool part about the implementation of startsWithVowel is that it won’t perform word.startsWith(vowel) on every single element in the array if it doesn’t need to do so. It only evaluates this until it finds an element which causes word.startsWith(vowel) to return true. In the case of “aardvark”, that’s the very first element.

You may be wondering “why do I have to use this Array.some method? I could have used a for loop.” Yup, you’re right. Here’s a different implementation which uses a for loop to do the same thing:

let startsWithVowelLoop = function(word) {
    let l = vowels.length;
    let result = false;
    for (let i = 0; i < l; i++) {
        if (word.startsWith(vowels[i])) {
            result = true;
            break;
        }
    }
    return result;
};

When I was first introduced to the some method, I had the same doubts. Why use this method to do something that I already knew how to do perfectly well with a loop? There are a couple of reasons. First, the code is shorter when written using the some method. That’s not such a big deal; sometimes short code is harder to read. However, in my opinion, it’s actually easier to read the implementation of startsWithVowel. My eye goes straight to some, and I know that method will just look for “some” value which satisfies the condition in the callback function. It’s also important that you’re going to find code like this all over the place, these days. Since you have to know what it means, it helps to use it in order to get comfortable with it.

In my next blog post, I’ll explore the performance differences between the for loop and the Array.some method.

If you found this interesting, click the subscribe button below! I write a new post about once a week.

editing React files in VS Code results in a Parsing error

Yesterday, I wrote about how I’ve tentatively switched over from Sublime Text editor to VS Code for my projects. Later, I started working on a JavaScript file, and realized that I was missing Sublime’s linter. So I turned on linting in VS Code by following the instructions in the VS Code marketplace for Dirk Bauemer’s ESLint.

Immediately, I got a complaint when I viewed a React file with an import statement at the top, like this:

import React from "react";
...

The word import had a squiggly red line under it. When I hovered over that, I saw the error message “Parsing error: The keyword ‘import’ is reserved eslint”. Like this:

Parsing error: the keyword 'import' is reserved

I found a git issue comment which explained how to fix it (for me! YMMV). Here’s how I did it.

First, I had to install ESLint-plugin-React: npm install -g eslint-plugin-react --save-dev

Then, I had to edit my VS Code json.settings. Here’s how: From the top menu, click File > Preferences > Settings. Your User and Workspace Settings area opens up, and there’s a handy search box at the top. Type in eslint and you’ll see a bunch of search results, including some links to “Edit in settings.json“. Click that link, and your settings.json file opens up. This is just a text file! For me, it is located under my home directory, in .config/Code/User/settings.json (I’m using Ubuntu 16.04). I got confused when I noticed that there was a settings.json file under the node_modules directory for my React project, as well (./node_modules/detect-port-alt/.vscode/settings.json). Don’t get distracted by additional files with that name. Just use the file which is shown by VS Code using the above procedure.

My json.settings originally looked like this:

{
    "editor.formatOnPaste": true,
    "editor.formatOnType": true,
    "editor.insertSpaces": false,
    "editor.detectIndentation": false,
    "editor.wordWrap": "on",
    "eslint.trace.server": "messages",
    "eslint.options" : {
        "useEslintrc": false
    }
}

All I had to do was add a new sub-option under eslint.options, as described in the git comment, like this:

{
    "editor.formatOnPaste": true,
    "editor.formatOnType": true,
    "editor.insertSpaces": false,
    "editor.detectIndentation": false,
    "editor.wordWrap": "on",
    "eslint.trace.server": "messages",
    "eslint.options" : {
        "useEslintrc": false,
        "parserOptions": {
            "ecmaVersion": 7,
            "sourceType": "module",
            "ecmaFeatures": {
                "jsx": true,
            }
        }
    }
}

Voilà! The linting error went away immediately; I didn’t have to reload the project or restart VS Code.

If you found this interesting, click the subscribe button below! I write a new post about once a week.

difference between == and === in javascript

The “triple equal”, “===”, is a strict comparison operator in JavaScript. It is used to compare two “things”, and returns either true or false.

The “double equal”, “==”, is an abstract comparison operator. It is also used to compare two “things”, and returns true or false.

They seem like the same thing! So, what’s the difference between “===” and “==” in JavaScript? And how do you remember which is which?

abstract comparison operator ==

When the “==” operator is used, the two operands – the things being compared – are converted to the same type by JavaScript before comparing.

This can be a source of some headaches! If you don’t realize that the two operands are actually being “messed with” before the “==” comparison occurs, you’re going to find this operator very confusing at some point!

You should mosey on over to the ECMAScript 5.1 specification, where the abstract equality comparison operator is explained.

Go ahead, take a look! Notice that there are 10 logic steps that are considered in computing the result of this operator, and the first one has 6 different substeps. It starts to become clear why the “==” (double equal, abstract equality comparison operator) can lead to “gotcha” bugs in code!

I am not going to quote the ECMAScript spec here, nor am I going to explain it in detail. Instead, I will give a couple of examples:

var a = ("1" == 1); // a is the boolean true
var b = ("true" == true); // b is the boolean false

If you aren’t already familiar with this behavior, the fact that ("1" == 1) is true may come as a surprise. And given that ("1" == 1) is true, it seems non-intuitive that ("true" == true) is false! This is where bugs can creep into code. For example, suppose an object {"custom" : "true"} is sent from the server to your client in the web browser, and the code to check for this custom option reads:

if (obj["custom"] == true) {
    doSomething();
}

The bug report says that when some custom option is checked, the doSomething method is not called, but it should be. So you start by printing out the value of obj["custom"], and you see true in the JavaScript console… how is that possible? Pain ensues!

strict comparison operator ===

In contrast, let’s take a look at what the spec says about the strict equals operator. There are 6 logic steps for this operator, and no substeps. It’s still not 100% straightforward (what’s that stuff about GetValue)? However, it’s definitely a bit less confusing.

Let’s look at how the triple equal plays out in the above code snippets:

var a = ("1" === 1); // a is the boolean false
var b = ("true" === true); // b is the boolean false

At least to me, these results seem much more obvious than the ones using “==“.

a mnemonic for remembering the difference

It’s difficult to get a truly intuitive feeling for what values will be returned by these two operators. However, I have a mnemonic that I use to help me. The three equal signs in the strict equals operator make me think “really, really, really!”. As in, the two operands are really, really, really equal. In particular, there’s no type conversion before the comparison. So if one operand is a string and the other is a number, you will always get false. On the other hand, the == operator will return true even if the two operands are “sort of” equal. That’s the way I think of it.

I almost never use the double equal, abstract comparison operator. In fact, I cannot think of the last time I used it! It strikes me as a source of hard-to-uncover bugs. And it’s hard to remember all the rules when using ==. However, I do know that there’s a difference between the two different operators. I think that’s the most important thing: experienced JavaScript developers should be aware that there’s a difference, and have a pretty good idea of what that difference is, even if they can’t quote the spec on it. If you’re a person who has expertise in several different languages, it gets hard to keep track of the finer details of a language. But you can still be very productive as long as you keep in mind some fundamental principles. In this case, make sure you notice when == is used and when === is used, be careful about which way you use them, and if you’re looking for a bug, keep in mind that the comparison operator is a place to check for the problem.

If you found this interesting, click the subscribe button below! I write a new post about once a week.