Cover image
Web Front-end
13 minute read

The 10 Most Common JavaScript Issues Developers Face

At first, JavaScript may seem quite simple. Yet the language is significantly more nuanced, powerful, and complex than one would initially be led to believe. Many of JavaScript’s subtleties lead to a number of common problems—10 of which we discuss here—that keep code from behaving as intended. It’s important to be aware of and avoid these pitfalls in one’s quest to become a master JavaScript developer.

Editor’s note: This article was updated by our editorial team on January 18, 2023. It has been modified to include recent sources and to align with our current editorial standards.

Today, JavaScript is at the core of virtually all modern web applications. That’s why JavaScript issues, and finding the mistakes that cause them, are at the forefront for web developers.

Powerful JavaScript-based libraries and frameworks for single page application (SPA) development, graphics and animation, and server-side JavaScript platforms are nothing new. JavaScript has become ubiquitous in the world of web app development and is therefore an increasingly important skill to master.

At first, JavaScript may seem quite simple. Indeed, building basic JavaScript functionality into a web page is a fairly straightforward task for any experienced software developer, even if they’re new to JavaScript. Yet the language is significantly more nuanced, powerful, and complex than one would initially believe. In fact, many of JavaScript’s subtleties can lead to a number of common problems that keep it from working—10 of which we discuss here. It is important to be aware of and avoid these issues on your journey to become a master JavaScript developer.

JavaScript Issue No. 1: Incorrect References to this

There’s no shortage of confusion among JavaScript developers regarding JavaScript’s this keyword.

As JavaScript coding techniques and design patterns have become increasingly sophisticated over the years, there’s been a corresponding increase in the proliferation of self-referencing scopes within callbacks and closures, which are a fairly common source of “this confusion” causing JavaScript issues.

Consider this example code snippet:

const Game = function() {
    this.clearLocalStorage = function() {
        console.log("Clearing local storage...");
    };
    this.clearBoard = function() {
        console.log("Clearing board...");
    };
};

Game.prototype.restart = function () {
    this.clearLocalStorage();
    this.timer = setTimeout(function() {
        this.clearBoard();    // What is "this"?
    }, 0);
};

const myGame = new Game();
myGame.restart();

Executing the above code results in the following error:

Uncaught TypeError: this.clearBoard is not a function

Why? It’s all about context. The reason you get that error is because, when you invoke setTimeout(), you are actually invoking window.setTimeout(). As a result, the anonymous function being passed to setTimeout() is being defined in the context of the window object, which has no clearBoard() method.

A traditional, old-browser-compliant solution is to simply save your reference to this in a variable that can then be inherited by the closure, e.g.:

Game.prototype.restart = function () {
    this.clearLocalStorage();
    const self = this;   // Save reference to 'this', while it’s still this!
    this.timer = setTimeout(function(){
        self.clearBoard();    // Oh, OK, I do know who 'self' is!
    }, 0);
};

Alternatively, in newer browsers, you can use the bind() method to pass in the proper reference:

Game.prototype.restart = function () {
    this.clearLocalStorage();
    this.timer = setTimeout(this.reset.bind(this), 0);  // Bind to 'this'
};

Game.prototype.reset = function(){
    this.clearBoard();    // OK, back in the context of the right 'this'!
};

JavaScript Issue No. 2: Thinking There Is Block-level Scope

As discussed in our JavaScript Hiring Guide, a common source of confusion among JavaScript developers (and therefore a common source of bugs) is assuming that JavaScript creates a new scope for each code block. Although this is true in many other languages, it is not true in JavaScript. Consider, for example, the following code:

for (var i = 0; i < 10; i++) {
    /* ... */
}
console.log(i);  // What will this output?

If you guess that the console.log() call would either output undefined or throw an error, you guessed incorrectly. Believe it or not, it will output 10. Why?

In most other languages, the code above would lead to an error because the “life” (i.e., scope) of the variable i would be restricted to the for block. In JavaScript, though, this is not the case, and the variable i remains in scope even after the for loop has completed, retaining its last value after exiting the loop. (This behavior is known as variable hoisting.)

Support for block-level scopes in JavaScript is available via the let keyword. The let keyword has been widely supported by browsers and back-end JavaScript engines like Node.js for years now.If that’s news to you, it’s worth taking the time to read up on scopes, prototypes, and more.

JavaScript Issue No. 3: Creating Memory Leaks

Memory leaks are almost inevitable issues in JavaScript if you’re not consciously coding to avoid them. There are numerous ways for them to occur, so we’ll just highlight two of their more common occurrences.

Memory Leak Example 1: Dangling References to Defunct Objects

Note: This example applies to legacy JavaScript engines only—modern ones have garbage collectors (GCs) that are smart enough to handle this case.

Consider the following code:

var theThing = null;
var replaceThing = function () {
  var priorThing = theThing;  // Hold on to the prior thing
  var unused = function () {
    // 'unused' is the only place where 'priorThing' is referenced,
    // but 'unused' never gets invoked
    if (priorThing) {
      console.log("hi");
    }
  };
  theThing = {
    longStr: new Array(1000000).join('*'),  // Create a 1MB object
    someMethod: function () {
      console.log(someMessage);
    }
  };
};
setInterval(replaceThing, 1000);    // Invoke 'replaceThing' once every second

If you run the above code and monitor memory usage, you’ll find that you’ve got a significant memory leak—a full megabyte per second! And even a manual garbage collector doesn’t help. So it looks like we are leaking longStr every time replaceThing is called. But why?

Memory leaks are almost inevitable issues in JavaScript if you’re not consciously coding to avoid them.

Let’s examine things in more detail:

Each theThing object contains its own 1MB longStr object. Every second, when we call replaceThing, it holds on to a reference to the prior theThing object in priorThing. But we still wouldn’t think this would be a problem, since, each time through, the previously referenced priorThing would be dereferenced (when priorThing is reset via priorThing = theThing;). Moreover, it is only referenced in the main body of replaceThing and in the function unused, which is, in fact, never used.

So again we’re left wondering why there is a memory leak here.

To understand what’s going on, we need to better understand the inner workings of JavaScript. Closures are typically implemented by every function object linking to a dictionary-style object representing its lexical scope. If both functions defined inside replaceThing actually used priorThing, it would be important that they both get the same object, even if priorThing gets assigned over and over so that both functions share the same lexical environment. But as soon as a variable is used by any closure, it ends up in the lexical environment shared by all closures in that scope. And that little nuance is what leads to this gnarly memory leak.

Memory Leak Example 2: Circular References

Consider this code fragment:

function addClickHandler(element) {
    element.click = function onClick(e) {
        alert("Clicked the " + element.nodeName)
    }
}

Here, onClick has a closure that keeps a reference to element (via element.nodeName). By also assigning onClick to element.click, the circular reference is created, i.e., elementonClickelementonClickelement

Interestingly, even if element is removed from the DOM, the circular self-reference above would prevent element and onClick from being collected and thus would become a memory leak.

Avoiding Memory Leaks: The Essentials

JavaScript’s memory management (and, in particular, its garbage collection) is largely based on the notion of object reachability.

The following objects are assumed to be reachable and are known as “roots”:

  • Objects referenced from anywhere in the current call stack (that is, all local variables and parameters in the functions currently being invoked, and all the variables in the closure scope)
  • All global variables

Objects are kept in memory at least as long as they are accessible from any of the roots through a reference or a chain of references.

There is a garbage collector in the browser that cleans memory occupied by unreachable objects; in other words, objects will be removed from memory if and only if the GC believes that they are unreachable. Unfortunately, it’s fairly easy to end up with defunct “zombie” objects that are no longer in use but that the GC still thinks are reachable.

JavaScript Issue No. 4: Confusion About Equality

One JavaScript convenience is that it will automatically coerce any value being referenced in a boolean context to a boolean value. But there are cases in which this can be as confusing as it is convenient. The following expressions, for example, are known to be troublesome for many a JavaScript developer:

// All of these evaluate to 'true'!
console.log(false == '0');
console.log(null == undefined);
console.log(" \t\r\n" == 0);
console.log('' == 0);

// And these do too!
if ({}) // ...
if ([]) // ...

With regard to the last two, despite being empty (which might lead you to believe that they would evaluate to false), both {} and [] are in fact objects, and any object will be coerced to a boolean value of true in JavaScript, consistent with the ECMA-262 specification.

As these examples demonstrate, the rules of type coercion can sometimes be as clear as mud. Accordingly, unless type coercion is explicitly desired, it’s typically best to use === and !== (rather than == and !=) to avoid any unintended side effects of type coercion. (== and != automatically perform type conversion when comparing two things, whereas === and !== do the same comparison without type conversion.)

Since we’re talking about type coercion and comparisons, it’s worth mentioning that comparing NaN with anything (even NaN!) will always return false. You therefore cannot use the equality operators (==, ===, !=, !==) to determine whether a value is NaN or not. Instead, use the built-in global isNaN() function:

console.log(NaN == NaN);    // False
console.log(NaN === NaN);   // False
console.log(isNaN(NaN));    // True

JavaScript Issue No. 5: Inefficient DOM Manipulation

JavaScript makes it relatively easy to manipulate the DOM (i.e., add, modify, and remove elements), but does nothing to promote doing so efficiently.

A common example is code that adds a series of DOM elements one at a time. Adding a DOM element is an expensive operation, and code that adds multiple DOM elements consecutively is inefficient and likely not to work well.

One effective alternative when multiple DOM elements need to be added is to use document fragments instead, which will improve efficiency and performance.

For example:

const div = document.getElementById("my_div");
const fragment = document.createDocumentFragment();
const elems = document.querySelectorAll('a');

for (let e = 0; e < elems.length; e++) {
    fragment.appendChild(elems[e]);
}
div.appendChild(fragment.cloneNode(true));

In addition to the inherently improved efficiency of this approach, creating attached DOM elements is expensive, whereas creating and modifying them while detached and then attaching them yields much better performance.

JavaScript Issue No. 6: Incorrect Use of Function Definitions Inside for Loops

Consider this code:

var elements = document.getElementsByTagName('input');
var n = elements.length;    // Assume we have 10 elements for this example
for (var i = 0; i < n; i++) {
    elements[i].onclick = function() {
        console.log("This is element #" + i);
    };
}

Based on the above code, if there were 10 input elements, clicking any of them would display “This is element #10”! This is because, by the time onclick is invoked for any of the elements, the above for loop will have completed and the value of i will already be 10 (for all of them).

Here’s how we can correct this JavaScript problem to achieve the desired behavior:

var elements = document.getElementsByTagName('input');
var n = elements.length;    // Assume we have 10 elements for this example
var makeHandler = function(num) {  // Outer function
     return function() {   // Inner function
         console.log("This is element #" + num);
     };
};
for (var i = 0; i < n; i++) {
    elements[i].onclick = makeHandler(i+1);
}

In this revised version of the code, makeHandler is immediately executed each time we pass through the loop, each time receiving the then-current value of i+1 and binding it to a scoped num variable. The outer function returns the inner function (which also uses this scoped num variable) and the element’s onclick is set to that inner function. This ensures that each onclick receives and uses the proper i value (via the scoped num variable).

JavaScript Issue No. 7: Failure to Properly Leverage Prototypal Inheritance

A surprisingly high number of JavaScript developers fail to fully understand, and therefore fully leverage, the features of prototypal inheritance.

Here’s a simple example:

BaseObject = function(name) {
    if (typeof name !== "undefined") {
        this.name = name;
    } else {
        this.name = 'default'
    }
};

This seems fairly straightforward. If you provide a name, use it, otherwise set the name to ‘default’. For instance:

var firstObj = new BaseObject();
var secondObj = new BaseObject('unique');

console.log(firstObj.name);  // -> Results in 'default'
console.log(secondObj.name); // -> Results in 'unique'

But what if we were to do this:

delete secondObj.name;

We’d then get:

console.log(secondObj.name); // -> Results in 'undefined'

But wouldn’t it be nicer for this to revert to ‘default’? This can easily be done if we modify the original code to leverage prototypal inheritance, as follows:

BaseObject = function (name) {
    if(typeof name !== "undefined") {
        this.name = name;
    }
};

BaseObject.prototype.name = 'default';

With this version, BaseObject inherits the name property from its prototype object, where it is set (by default) to 'default'. Thus, if the constructor is called without a name, the name will default to default. Similarly, if the name property is removed from an instance of BaseObject, the prototype chain will then be searched and the name property will be retrieved from the prototype object where its value is still 'default'. So now we get:

var thirdObj = new BaseObject('unique');
console.log(thirdObj.name);  // -> Results in 'unique'

delete thirdObj.name;
console.log(thirdObj.name);  // -> Results in 'default'

JavaScript Issue No. 8: Creating Incorrect References to Instance Methods

Let’s define a simple object, and create an instance of it, as follows:

var MyObjectFactory = function() {}
	
MyObjectFactory.prototype.whoAmI = function() {
    console.log(this);
};

var obj = new MyObjectFactory();

Now, for convenience, let’s create a reference to the whoAmI method, presumably so we can access it merely by whoAmI() rather than the longer obj.whoAmI():

var whoAmI = obj.whoAmI;

And just to be sure we’ve stored a reference to a function, let’s print out the value of our new whoAmI variable:

console.log(whoAmI);

Outputs:

function () {
    console.log(this);
}

It looks fine so far.

But look at the difference when we invoke obj.whoAmI() versus our convenience reference whoAmI():

obj.whoAmI();  // Outputs "MyObjectFactory {...}" (as expected)
whoAmI();      // Outputs "window" (uh-oh!)

What went wrong? Our whoAmI() call is in the global namespace, so this gets set to window (or, in strict mode, to undefined), not to the obj instance of MyObjectFactory! In other words, the value of this normally depends on the calling context.

Arrow functions ((params) => {} instead of function(params) {} provide a static this that is not based on the calling context like this is for regular functions. This gives us a workaround:

var MyFactoryWithStaticThis = function() {
    this.whoAmI = () => { // Note the arrow notation here
        console.log(this);
    };
}

var objWithStaticThis = new MyFactoryWithStaticThis();
var whoAmIWithStaticThis = objWithStaticThis.whoAmI;

objWithStaticThis.whoAmI();  // Outputs "MyFactoryWithStaticThis" (as usual)
whoAmIWithStaticThis();      // Outputs "MyFactoryWithStaticThis" (arrow notation benefit)

You may have noticed that, even though we got the output to match, this is a reference to the factory, rather than to the instance. Rather than trying to fix this issue further, it’s worth considering approaches to JavaScript that don’t rely on this (or even new) at all, as explained in As a JS Developer, This Is What Keeps Me Up at Night.

JavaScript Issue No. 9: Providing a String As the First Argument to setTimeout or setInterval

For starters, let’s be clear on something here: Providing a string as the first argument to setTimeout or setInterval is not itself a mistake per se. It is perfectly legitimate JavaScript code. The issue here is more one of performance and efficiency. What is often overlooked is that if you pass in a string as the first argument to setTimeout or setInterval, it will be passed to the function constructor to be converted into a new function. This process can be slow and inefficient, and is rarely necessary.

The alternative to passing a string as the first argument to these methods is to instead pass in a function. Let’s look at an example.

Here, then, would be a fairly typical use of setInterval and setTimeout, passing a string as the first parameter:

setInterval("logTime()", 1000);
setTimeout("logMessage('" + msgValue + "')", 1000);

The better choice would be to pass in a function as the initial argument, e.g.:

setInterval(logTime, 1000);   // Passing the logTime function to setInterval
	
setTimeout(function() {       // Passing an anonymous function to setTimeout
    logMessage(msgValue);     // (msgValue is still accessible in this scope)
}, 1000);

JavaScript Issue No. 10: Failure to Use “Strict Mode”

As explained in our JavaScript Hiring Guide, “strict mode” (i.e., including 'use strict'; at the beginning of your JavaScript source files) is a way to voluntarily enforce stricter parsing and error handling on your JavaScript code at runtime, as well as a way to make your code more secure.

While, admittedly, failing to use strict mode is not truly a “mistake,” its use is increasingly being encouraged and its omission is increasingly considered bad form.

Here are some key benefits of strict mode:

  • Makes debugging easier. Code errors that would otherwise have been ignored or would have failed silently will now generate errors or throw exceptions, alerting you sooner to problems with JavaScript in your code base and directing you more quickly to their source.
  • Prevents accidental globals. Without strict mode, assigning a value to an undeclared variable automatically creates a global variable with that name. This is one of the most common JavaScript errors. In strict mode, attempting to do so throws an error.
  • Eliminates this coercion. Without strict mode, a reference to a this value of null or undefined is automatically coerced to the globalThis variable. This can cause many frustrating bugs. In strict mode, referencing a this value of null or undefined throws an error.
  • Disallows duplicate property names or parameter values. Strict mode throws an error when it detects a duplicate named property in an object (e.g., var object = {foo: "bar", foo: "baz"};) or a duplicate named argument for a function (e.g., function foo(val1, val2, val1){}), thereby catching what is almost certainly a bug in your code that you might otherwise have wasted significant time tracking down.
  • Makes eval() safer. There are some differences in the way eval() behaves in strict mode and in nonstrict mode. Most significantly, in strict mode, variables and functions declared inside an eval() statement are not created in the containing scope. (They are created in the containing scope in nonstrict mode, which can also be a common source of problems with JavaScript.)
  • Throws an error on invalid use of delete. The delete operator (used to remove properties from objects) cannot be used on nonconfigurable properties of the object. Nonstrict code will fail silently when an attempt is made to delete a nonconfigurable property, whereas strict mode will throw an error in such a case.

Mitigating JavaScript Issues With a Smarter Approach

As is true with any technology, the better you understand why and how JavaScript works and doesn’t work, the more solid your code will be and the more you’ll be able to effectively harness the true power of the language. Conversely, a lack of proper understanding of JavaScript paradigms and concepts is where many JavaScript problems lie.Thoroughly familiarizing yourself with the language’s nuances and subtleties is the most effective strategy for improving your proficiency and increasing your productivity.


Further Reading on the Toptal Engineering Blog:

Understanding the basics

The common errors that developers make while coding in JavaScript include mistaken thinking about how the "this" keyword works, incorrect assumptions about block scoping, and a failure to avoid memory leaks. JavaScript's evolution over time has left many pitfalls if old coding patterns are followed.

You can improve your JavaScript skills by putting best practices to use in real code, and reading about the nuances inherent in the language to be aware of its more advanced features and limitations.

Buggy code can look perfectly innocent on the surface. By learning about common JavaScript issues, you can start to understand what makes certain coding patterns problematic and how to avoid them in your own code.

Some might contend that the JavaScript language itself is problematic. Indeed, it has its shortcomings, but it's also ubiquitous—so it pays to understand how to navigate them if you (like most of today's developers) have to work with some form of JavaScript code.

Comments

boriscy
Great article #7 was the best.
boriscy
Great article #7 was the best.
Julio Saito
Good post. Alternatively, on mistake #8, you can use: var whoAmI = obj.whoAmI.bind(obj); whoAmI(); // outputs "MyObj" (as expected)
Julio Saito
Good post. Alternatively, on mistake #8, you can use: var whoAmI = obj.whoAmI.bind(obj); whoAmI(); // outputs "MyObj" (as expected)
hasanyasin
Great article. I will make a few little additions, mostly considering people who are relatively new at JavaScript. For #2, example 2, it may be useful mentioning to avoid use of `element` inside the function, they can access the element using function arguments and `this` instead. For #6: IMHO, it is not a good practice to create closures for elements this way. This is given as an example so many times online that I guess, anybody trying to learn JavaScript will pick this up as a pattern. I do this on a set of elements which I am sure that will be very limited in numbers. In other cases, I prefer adding attributes to DOM objects themselves and then reaching it from inside the event handler.. For #8: I guess at the end of the section, it would be useful to add use of `bind` to do this. Given example shows only the problem; but not really guides us how to do things: I already have obj.method and it really doesn't matter if I have obj.method_shortcut. I saw many developers trying to have a shortcut for console.log and then quitting when they see that; `log = console.log` doesn't work as they expected. It is easy to have a shortcut for console.log, though: `log = console.log.bind(console)` Then you can use log() as a shortcut. This is just nice especially when dirty-debugging using console instead of debuggers. Another place where you want a shortcut is using `hasOwnProperty` method of `Object` prototype. You can have your shortcut, let's say `hasprop` like this; ``` hasprop = Function.call.bind(Object.prototype.hasOwnProperty) ``` Then instead of this: ``` Object.prototype.hasOwnProperty.call(myobj, property_name) ``` you can do this: ``` hasprop(myboj, property_name) ``` It surprises me when I see engineers who are mad at use of .length attribute in loop bodies and conditions instead of caching it before the loop mostly with the concerns for the effect of attribute access on the performance; then writing loops with such chains of attribute access. I believe `hasOwnProperty` is a good example for this. I love `bind`. It makes me feel like I am almost in Haskel :p //partial application. Haskel: ``` add a b = a + b add5 = add 5 ``` JavaScript: ``` function add(a,b) { return a+b } var add5 = add.bind(null, 5); ``` Awesome, isn't it? Just to keep in mind that first parameter to bind is `this` inside the function body so second parameter to `bind` becomes the first parameter to your function. If you give `null` as the first argument to `bind` then it won't set `this` for the function. As a side note, `this` was used to refer to global object (`window` in browser) when a function is called with `null` for `this`; but in strict mode, this behavior has changed and `this` will be `null` if you call it with `null` using bind/call/apply functions.
hasanyasin
Great article. I will make a few little additions, mostly considering people who are relatively new at JavaScript. For #2, example 2, it may be useful mentioning to avoid use of `element` inside the function, they can access the element using function arguments and `this` instead. For #6: IMHO, it is not a good practice to create closures for elements this way. This is given as an example so many times online that I guess, anybody trying to learn JavaScript will pick this up as a pattern. I do this on a set of elements which I am sure that will be very limited in numbers. In other cases, I prefer adding attributes to DOM objects themselves and then reaching it from inside the event handler.. For #8: I guess at the end of the section, it would be useful to add use of `bind` to do this. Given example shows only the problem; but not really guides us how to do things: I already have obj.method and it really doesn't matter if I have obj.method_shortcut. I saw many developers trying to have a shortcut for console.log and then quitting when they see that; `log = console.log` doesn't work as they expected. It is easy to have a shortcut for console.log, though: `log = console.log.bind(console)` Then you can use log() as a shortcut. This is just nice especially when dirty-debugging using console instead of debuggers. Another place where you want a shortcut is using `hasOwnProperty` method of `Object` prototype. You can have your shortcut, let's say `hasprop` like this; ``` hasprop = Function.call.bind(Object.prototype.hasOwnProperty) ``` Then instead of this: ``` Object.prototype.hasOwnProperty.call(myobj, property_name) ``` you can do this: ``` hasprop(myboj, property_name) ``` It surprises me when I see engineers who are mad at use of .length attribute in loop bodies and conditions instead of caching it before the loop mostly with the concerns for the effect of attribute access on the performance; then writing loops with such chains of attribute access. I believe `hasOwnProperty` is a good example for this. I love `bind`. It makes me feel like I am almost in Haskel :p //partial application. Haskel: ``` add a b = a + b add5 = add 5 ``` JavaScript: ``` function add(a,b) { return a+b } var add5 = add.bind(null, 5); ``` Awesome, isn't it? Just to keep in mind that first parameter to bind is `this` inside the function body so second parameter to `bind` becomes the first parameter to your function. If you give `null` as the first argument to `bind` then it won't set `this` for the function. As a side note, `this` was used to refer to global object (`window` in browser) when a function is called with `null` for `this`; but in strict mode, this behavior has changed and `this` will be `null` if you call it with `null` using bind/call/apply functions.
ajaniashish
Really nice article and mistakes you mentioned in this post are often made by programmers, but most common mistakes in my view are #1 and #3, often when I review the code of my team members I see these two mistakes made and they are completely unaware of it. Thank you for sharing such nice article.
ajaniashish
Really nice article and mistakes you mentioned in this post are often made by programmers, but most common mistakes in my view are #1 and #3, often when I review the code of my team members I see these two mistakes made and they are completely unaware of it. Thank you for sharing such nice article.
Tamm
Great article.
Tamm
Great article.
sebastianteres
Great Post! I would recommend going through Mozilla's Javascript guide (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/About) It covers most of the topics discussed here. Its a great starting point for javascript developers.
sebastianteres
Great Post! I would recommend going through Mozilla's Javascript guide (https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/About) It covers most of the topics discussed here. Its a great starting point for javascript developers.
brianN2
Nice article - just missing the Common mistake # 0 Using javascript in the first place! If you wanted a language that would make for horrible code, difficult maintenance and ease of bug creation javascript has it all! JavaScript was never meant to do what it does today, every new feature just makes the language worse and more complicated to use. Unfortunately it's something every successful language suffers from c++ has similar problems. Everything has to be backwards compatible, so things never get simpler only more complicated. As javascript is used in sites that might never be maintained it ain't never going to go away. Articles like this are great but they only scratch the surface of the things done in the name of JavaScript!
brianN2
Nice article - just missing the Common mistake # 0 Using javascript in the first place! If you wanted a language that would make for horrible code, difficult maintenance and ease of bug creation javascript has it all! JavaScript was never meant to do what it does today, every new feature just makes the language worse and more complicated to use. Unfortunately it's something every successful language suffers from c++ has similar problems. Everything has to be backwards compatible, so things never get simpler only more complicated. As javascript is used in sites that might never be maintained it ain't never going to go away. Articles like this are great but they only scratch the surface of the things done in the name of JavaScript!
Melad Dabbous
Good article. I learned a lot from it.
Melad Dabbous
Good article. I learned a lot from it.
Ryan J. Peterson
I agree that #6 should have been something that wasn't a DOM element. I think the reason it is used online so much is `onclick` is one of the functions that people are first introduced too. My focus was more on the closure not being inside of the loop than it being on the DOM event. I had in one draft of this mentioned bind but edited it out for sake of readability, this post really could be extended even more than it is but then what would be left to discuss in the comments. Thanks for adding value here in the comments though, hopefully learners will read the comments as well.
Ryan J. Peterson
I agree that #6 should have been something that wasn't a DOM element. I think the reason it is used online so much is `onclick` is one of the functions that people are first introduced too. My focus was more on the closure not being inside of the loop than it being on the DOM event. I had in one draft of this mentioned bind but edited it out for sake of readability, this post really could be extended even more than it is but then what would be left to discuss in the comments. Thanks for adding value here in the comments though, hopefully learners will read the comments as well.
Ryan J. Peterson
This is a great recommendation, I reference this guide often when looking up something I can't remember or want to make sure I am correct on.
Ryan J. Peterson
This is a great recommendation, I reference this guide often when looking up something I can't remember or want to make sure I am correct on.
Ryan J. Peterson
It is the same situation with comments that don't add value to exercises in learning. Frankly, JavaScript isn't going to go away anytime soon. With the ECMA 6 and v8 revolution, it is at least being improved upon. To say "JavaScript was never meant to do what it does today..." ignores that by breaking the intent of technology, we have seen advancements such as the internet, which has broken out of the intent for better communication into a multitude of possibilities. While I value your opinion, I still feel like blanket flame comments about JavaScript, Ruby, PHP or any other language creates an unnecessary division between what is a subjective decision of programming language and environment typically not made by us writing the code. In the future, I would appreciate comments aiming to be constructive. Thank you.
Ryan J. Peterson
It is the same situation with comments that don't add value to exercises in learning. Frankly, JavaScript isn't going to go away anytime soon. With the ECMA 6 and v8 revolution, it is at least being improved upon. To say "JavaScript was never meant to do what it does today..." ignores that by breaking the intent of technology, we have seen advancements such as the internet, which has broken out of the intent for better communication into a multitude of possibilities. While I value your opinion, I still feel like blanket flame comments about JavaScript, Ruby, PHP or any other language creates an unnecessary division between what is a subjective decision of programming language and environment typically not made by us writing the code. In the future, I would appreciate comments aiming to be constructive. Thank you.
brianN2
Sorry you didn't get the light hearted nature of the comment or the point being made! JavaScript is one of my working languages as is C++ so it's hardly going to be a flame on those languages. The comment is constructive and appropriate on an article regarding common mistakes, if the language was better then the problems would be fewer! What would be great is a ' use superstrict' that brings in strict type checking and real oops programming, removes some of the less desirable features, perhaps for a future version - I can dream!
brianN2
Sorry you didn't get the light hearted nature of the comment or the point being made! JavaScript is one of my working languages as is C++ so it's hardly going to be a flame on those languages. The comment is constructive and appropriate on an article regarding common mistakes, if the language was better then the problems would be fewer! What would be great is a ' use superstrict' that brings in strict type checking and real oops programming, removes some of the less desirable features, perhaps for a future version - I can dream!
Ryan J. Peterson
My bad. I have been dealing with negative log trolls lately and the humor was lost on me. Yes, a future version is where we can rest our hopes and dreams.
Ryan J. Peterson
My bad. I have been dealing with negative log trolls lately and the humor was lost on me. Yes, a future version is where we can rest our hopes and dreams.
Sushil Kumar
Great article.. These are the common mistakes novice programmers, like me, make. Specially the #1 and #2
Sushil Kumar
Great article.. These are the common mistakes novice programmers, like me, make. Specially the #1 and #2
MobilePundits
Most of the time when the project deadline is near and due to this In the hurry of development and releasing most of the people don't pay attention over all these java script mistakes. You shared a nice and informative post. I recommended. <a href="http://www.mobilepundits.com/PhoneGap_Development.html">Phonegap mobile app development</a>
MobilePundits
Most of the time when the project deadline is near and due to this In the hurry of development and releasing most of the people don't pay attention over all these java script mistakes. You shared a nice and informative post. I recommended. <a href="http://www.mobilepundits.com/PhoneGap_Development.html">Phonegap mobile app development</a>
Vladimir Grichina
Equality in JS is so confusing that you also have made a mistake when describing mistake #4 :) <code>isNaN</code> won't really check if value is NaN, some examples: <pre><code> isNaN("foo") == true // this string cannot be converted to number isNaN("123") == false // string can be converted to number isNaN([1, 2])) == false isNaN([1, 2]) == true </code></pre> To check if value <code>x</code> is NaN you have to compare it to itself, i.e.: <pre><code> function isReallyNaN(x) { return x != x; } isReallyNaN(1) == false isReallyNaN(NaN) == true </code></pre>
Vladimir Grichina
Equality in JS is so confusing that you also have made a mistake when describing mistake #4 :) <code>isNaN</code> won't really check if value is NaN, some examples: <pre><code> isNaN("foo") == true // this string cannot be converted to number isNaN("123") == false // string can be converted to number isNaN([1, 2])) == false isNaN([1, 2]) == true </code></pre> To check if value <code>x</code> is NaN you have to compare it to itself, i.e.: <pre><code> function isReallyNaN(x) { return x != x; } isReallyNaN(1) == false isReallyNaN(NaN) == true </code></pre>
Sergey Batishchev
Great article. Can you clarify though exact extent of the problem here: "Interestingly, even if element is removed from the DOM, the circular self-reference above would prevent element and onClick from being collected, and hence, a memory leak." I was under impression that DOM-JS type circular references leaks were only an issues for IE7 and below (due to the separate handling of GC for DOM and JS object if I recall it right). Because, really, circular references are not an issue for GC, as long as objects in a "loop" are not reachable from the outside. Or I am missing something in your example that in fact holds one of the objects from the outside?
Sergey Batishchev
Great article. Can you clarify though exact extent of the problem here: "Interestingly, even if element is removed from the DOM, the circular self-reference above would prevent element and onClick from being collected, and hence, a memory leak." I was under impression that DOM-JS type circular references leaks were only an issues for IE7 and below (due to the separate handling of GC for DOM and JS object if I recall it right). Because, really, circular references are not an issue for GC, as long as objects in a "loop" are not reachable from the outside. Or I am missing something in your example that in fact holds one of the objects from the outside?
Kostas
An alternative for #6 using IIFE... <pre><code class="javascript"> var elements = document.getElementsByTagName('input'); var n = elements.length; for (var i = 0; i < n; i++) { ( function( num ){ elements[i].onclick = function() { console.log( "This is element #" + ( num+1 ) ); }; }( i ) ); } </code></pre>
Kostas
An alternative for #6 using IIFE... <pre><code class="javascript"> var elements = document.getElementsByTagName('input'); var n = elements.length; for (var i = 0; i < n; i++) { ( function( num ){ elements[i].onclick = function() { console.log( "This is element #" + ( num+1 ) ); }; }( i ) ); } </code></pre>
Guest
Memory Leak Example #1 seems to be not valid. There is no memory leak there. Each time function replaceThing() is executed priorThing set to undefined first and then get ref to theThing so it take 1mb of memory each time and no mem leaks.
Guest
Memory Leak Example #1 seems to be not valid. There is no memory leak there. Each time function replaceThing() is executed priorThing set to undefined first and then get ref to theThing so it take 1mb of memory each time and no mem leaks.
iknowbest
Just came across this one today: var x = 12; var y=10; var out = (y==10 && x); console.log(out) // outputs '12' and not true or false; would love an explanation if anyone has one.
iknowbest
Just came across this one today: var x = 12; var y=10; var out = (y==10 && x); console.log(out) // outputs '12' and not true or false; would love an explanation if anyone has one.
Anon
JavaScript has more than "true" and "false" truthy/falsy values, and will return the "last value" for |, ||, &, and && operators. http://en.wikipedia.org/wiki/Short-circuit_evaluation JavaScript developers may use this to their advantage: // without using last value function(name) { if (name) { return name; } return "Candy"; } // using last value function(name) { return name || "Candy"; // if name is "truthy", we stop evaluation and return it. //Otherwise we evaluate RHS and return "candy" }
Anon
JavaScript has more than "true" and "false" truthy/falsy values, and will return the "last value" for |, ||, &, and && operators. http://en.wikipedia.org/wiki/Short-circuit_evaluation JavaScript developers may use this to their advantage: // without using last value function(name) { if (name) { return name; } return "Candy"; } // using last value function(name) { return name || "Candy"; // if name is "truthy", we stop evaluation and return it. //Otherwise we evaluate RHS and return "candy" }
cintalauraramarimari
JavaScript is very important for modern web applications, let's say <a href="http://obatkeputihanonline.com/">obat keputihan gatal berbau</a> to the health of women
cintalauraramarimari
JavaScript is very important for modern web applications, let's say <a href="http://obatkeputihanonline.com/">obat keputihan gatal berbau</a> to the health of women
Ben Randles-Dunkley
You mean AS3? ;)
Ben Randles-Dunkley
You mean AS3? ;)
Terry Marr
Great post! Beginners need concrete examples of good and bad code to learn from. You did this nicely, especially with #3 memory leak example 1. However, in example 2, the circular reference example, it would be nice to see the fixed version of the code. Can you edit to provide that too?
Terry Marr
Great post! Beginners need concrete examples of good and bad code to learn from. You did this nicely, especially with #3 memory leak example 1. However, in example 2, the circular reference example, it would be nice to see the fixed version of the code. Can you edit to provide that too?
Ali
Will never understand one thing. If its such an illogical language(which it is) with so many blunders then why are people still using it?
Ali
Will never understand one thing. If its such an illogical language(which it is) with so many blunders then why are people still using it?
javinievas
You forgot to mention the trailing comma issue. I've seen it a lot. dict = {"a":1, "b":2, }
javinievas
You forgot to mention the trailing comma issue. I've seen it a lot. dict = {"a":1, "b":2, }
Robert Jackson
TOPAL... has a person send me an email asking me to set up a time for interview. Times offered were between 2 am and 8 am. I send an email back saying that is insane. I get told I will hear from someone else who can be in my time zone. I never hear back.. Where the hell is toptal located????????????????????? Thanks for a new idea for a new website. How about trying to have people in the country who are awake at the time of interviews and calls before pretending to be a real company??????????????????????
Robert Jackson
TOPAL... has a person send me an email asking me to set up a time for interview. Times offered were between 2 am and 8 am. I send an email back saying that is insane. I get told I will hear from someone else who can be in my time zone. I never hear back.. Where the hell is toptal located????????????????????? Thanks for a new idea for a new website. How about trying to have people in the country who are awake at the time of interviews and calls before pretending to be a real company??????????????????????
Norbert
No need for IIFE here, use a Array Prototype method like .forEach. Saves many keystrokes and make the code easier to reason about and read. Converting the nodeList to an Array first is important though, but that's easy too! Array.from(document.getElementsByTagName('input')).forEach(function (item, index) { item.addEventListener('click', function (event) { console.log("This is element #" + index); }); }); As you can see, there's no need for variables, that just hang around and cannot be GC'd. Working example: http://jsbin.com/bexohageje/edit?html,js,console
Norbert
No need for IIFE here, use a Array Prototype method like .forEach. Saves many keystrokes and make the code easier to reason about and read. Converting the nodeList to an Array first is important though, but that's easy too! Array.from(document.getElementsByTagName('input')).forEach(function (item, index) { item.addEventListener('click', function (event) { console.log("This is element #" + index); }); }); As you can see, there's no need for variables, that just hang around and cannot be GC'd. Working example: http://jsbin.com/bexohageje/edit?html,js,console
Kostas
Neat! Although, I think for the time being, Array.prototype.from needs a polyfill to work across all browsers.
Kostas
Neat! Although, I think for the time being, Array.prototype.from needs a polyfill to work across all browsers.
Norbert
Correct, but polyfills are A-OK with me. <pre><code> Polyfill is super easy too: Array.from = Array.from || function (thing) { return [].splice.call(thing); }; </code></pre> working example: http://jsbin.com/nuxucirudo/edit?html,js,console
Norbert
Correct, but polyfills are A-OK with me. <pre><code> Polyfill is super easy too: Array.from = Array.from || function (thing) { return [].splice.call(thing); }; </code></pre> working example: http://jsbin.com/nuxucirudo/edit?html,js,console
Norbert
> It's implemented in every browser in use. > All computers come with browsers by default. > Browsers are pretty much required for doing anything online. > It's actually a very dynamic expressive and powerful language. > No other programming language is enabled in browser by default. But fear not! If you don't like javascript, you don't have to use it! You can transpile/compile to javascript from many languages you might like. TypeScript, Ruby, C, Scala just to name a few. With asm.js support, the code these tools generate can actually be really fast. Just hope they come with a good debugger, because otherwise you're &^*%ed.
Norbert
> It's implemented in every browser in use. > All computers come with browsers by default. > Browsers are pretty much required for doing anything online. > It's actually a very dynamic expressive and powerful language. > No other programming language is enabled in browser by default. But fear not! If you don't like javascript, you don't have to use it! You can transpile/compile to javascript from many languages you might like. TypeScript, Ruby, C, Scala just to name a few. With asm.js support, the code these tools generate can actually be really fast. Just hope they come with a good debugger, because otherwise you're &^*%ed.
Norbert
I'm very confused by this as well, So this is broken, because of reasons the article explains: <pre><code> function addClickHandler(element) { element.click = function onClick(e) { alert("Clicked the " + element.nodeName) } } </code></pre> Perhaps we can try to do away with the 'element' reference like this: <pre><code> var addClickHandler = function (element) { element.addEventListener('click', function (event) { alert("Clicked the " + event.currentTarget.nodeName) }); }; </code></pre> Working example: http://jsbin.com/becamexive/edit?html,js,output NOTE: I had to edit the authors code, because it wasn't working/doing anything/the thing that was intended.
Norbert
I'm very confused by this as well, So this is broken, because of reasons the article explains: <pre><code> function addClickHandler(element) { element.click = function onClick(e) { alert("Clicked the " + element.nodeName) } } </code></pre> Perhaps we can try to do away with the 'element' reference like this: <pre><code> var addClickHandler = function (element) { element.addEventListener('click', function (event) { alert("Clicked the " + event.currentTarget.nodeName) }); }; </code></pre> Working example: http://jsbin.com/becamexive/edit?html,js,output NOTE: I had to edit the authors code, because it wasn't working/doing anything/the thing that was intended.
Norbert
<pre><code> var out = (doThis && doThat && returnThisThing) </code></pre> doThis is attempted, if it returns a truthy value the next thing it attempted, etc. until the last thing in the sequence and that is whatever is actually returned from the expression. Javascript considers 0, null, undefined, '' as falsy and everything else is considered truthy. I personally would have liked an empty array to have been falsy, but Ey, can't have it all I guess.
Norbert
<pre><code> var out = (doThis && doThat && returnThisThing) </code></pre> doThis is attempted, if it returns a truthy value the next thing it attempted, etc. until the last thing in the sequence and that is whatever is actually returned from the expression. Javascript considers 0, null, undefined, '' as falsy and everything else is considered truthy. I personally would have liked an empty array to have been falsy, but Ey, can't have it all I guess.
Norbert
You may investigate transpiling/compiling to javascript from whatever language you DO like. You can write stinky code in any language though, but it's easier in some then in others. Yes it's very easy to make errors in Javascript, doesn't mean there's absolutely no beauty there and we should get rid of all of it, though. Personally I don't agree that another 'mode' in javascript would be an improvement. TC39 seems to be in agreement on that most of the time. Exactly what additions in ES5 and ES6 (besides classes) do you actually think make the language worse? I genuinely am curious why you think the language is evolving in a bad way. Kind regards, no flame intended
Norbert
You may investigate transpiling/compiling to javascript from whatever language you DO like. You can write stinky code in any language though, but it's easier in some then in others. Yes it's very easy to make errors in Javascript, doesn't mean there's absolutely no beauty there and we should get rid of all of it, though. Personally I don't agree that another 'mode' in javascript would be an improvement. TC39 seems to be in agreement on that most of the time. Exactly what additions in ES5 and ES6 (besides classes) do you actually think make the language worse? I genuinely am curious why you think the language is evolving in a bad way. Kind regards, no flame intended
brianN2
Strangely enough think a lot of the new features actually make JavaScript better (!), go strict and it gets even better. The trouble is the larger you grow a languages surface area then the harder it becomes to learn and use correctly, more the chance for errors and undefined behaviour. A language that needs '===' as well as '==' really has a problem! You are definitely correct in that transpiling/compiling to JavaScript would be a way to go. Compilers don't have fragility (or egos!) of us human programers. So maybe a compiled sub set of the language which is 'modern' that removes all the ambiguities and baggage of JavaScript is the way to go?
brianN2
Strangely enough think a lot of the new features actually make JavaScript better (!), go strict and it gets even better. The trouble is the larger you grow a languages surface area then the harder it becomes to learn and use correctly, more the chance for errors and undefined behaviour. A language that needs '===' as well as '==' really has a problem! You are definitely correct in that transpiling/compiling to JavaScript would be a way to go. Compilers don't have fragility (or egos!) of us human programers. So maybe a compiled sub set of the language which is 'modern' that removes all the ambiguities and baggage of JavaScript is the way to go?
bdiscus
forEach is a great solution to many things, but it has it's drawbacks. It's very slow compared to a simple cached for loop, as it constitutes a function call for each iteration which is pretty expensive. So if you were going to process a big deal of elements you should use a simple cached for loop, if not then forEach would be ok. Performance comparisons here (forEach 73% slower for me, Chrome): https://jsperf.com/for-vs-foreach/37
bdiscus
forEach is a great solution to many things, but it has it's drawbacks. It's very slow compared to a simple cached for loop, as it constitutes a function call for each iteration which is pretty expensive. So if you were going to process a big deal of elements you should use a simple cached for loop, if not then forEach would be ok. Performance comparisons here (forEach 73% slower for me, Chrome): https://jsperf.com/for-vs-foreach/37
BeGe1
#8 is incorrect. It states that the reason for the change in the "this" keyword is that the variable declaration pointing to the function is <strong>created</strong> in the global scope. This is incorrect. The "this" keyword is a matter of dynamic scope, not lexical. It's <em>not</em> about where the variable pointing to the function is declared, <strong>it's about how it's called</strong>. The reason the first one outputs "MyObj" is because it's called as an object property, so that object becomes the "this" keyword. The second one is called <em>not</em> as an object property, so its "this" keyword is whatever the default "this" is (in this case the global object window since it's not in strict mode). Proof of that is this code, add it to the end of the code you were doing: <pre>(function myFunc(){ var whoAmI2 = whoAmI; whoAmI2(); // outputs "window", even though was "declared" in a function })(); function MyConstructor() { var whoAmI3 = whoAmI; whoAmI3(); } var mc = new MyConstructor(); // "window", even though is declared in an instantiated object</pre> Why does it do that? Again...because it's about how it's called, not where it's declared. Just like <code>whoAmI</code>, <code>whoAmI2</code> and <code>whoAmI3</code> are called NOT as a property on an object, so (not in strict mode) it ends up with the "this" keyword meaning the global object (i.e. window) just the same as <code>whoAmI</code> even though the variables pointing to them are declared in vastly different circumstances.
BeGe1
#8 is incorrect. It states that the reason for the change in the "this" keyword is that the variable declaration pointing to the function is <strong>created</strong> in the global scope. This is incorrect. The "this" keyword is a matter of dynamic scope, not lexical. It's <em>not</em> about where the variable pointing to the function is declared, <strong>it's about how it's called</strong>. The reason the first one outputs "MyObj" is because it's called as an object property, so that object becomes the "this" keyword. The second one is called <em>not</em> as an object property, so its "this" keyword is whatever the default "this" is (in this case the global object window since it's not in strict mode). Proof of that is this code, add it to the end of the code you were doing: <pre>(function myFunc(){ var whoAmI2 = whoAmI; whoAmI2(); // outputs "window", even though was "declared" in a function })(); function MyConstructor() { var whoAmI3 = whoAmI; whoAmI3(); } var mc = new MyConstructor(); // "window", even though is declared in an instantiated object</pre> Why does it do that? Again...because it's about how it's called, not where it's declared. Just like <code>whoAmI</code>, <code>whoAmI2</code> and <code>whoAmI3</code> are called NOT as a property on an object, so (not in strict mode) it ends up with the "this" keyword meaning the global object (i.e. window) just the same as <code>whoAmI</code> even though the variables pointing to them are declared in vastly different circumstances.
James Edward Lewis
NaN is also falsy, and curiously, the first versions of JavaScript had new Boolean(false) being falsy too.
James Edward Lewis
NaN is also falsy, and curiously, the first versions of JavaScript had new Boolean(false) being falsy too.
James Edward Lewis
I also understand that old versions of IE (again, IE7-) used reference-counting rather than mark-and-sweep, so that reference cycles that were not actually reachable from global code or the current call stack would not be freed, even if only native JS objects were involved.
James Edward Lewis
I also understand that old versions of IE (again, IE7-) used reference-counting rather than mark-and-sweep, so that reference cycles that were not actually reachable from global code or the current call stack would not be freed, even if only native JS objects were involved.
James Edward Lewis
That just might become a reality with the 'use strong' proposal, now implemented in V8.
James Edward Lewis
That just might become a reality with the 'use strong' proposal, now implemented in V8.
James Edward Lewis
The example at the end of #1 should be rewritten to get at the heart of the matter: Game.prototype.restart = function () { this.clearLocalStorage(); this.timer = setTimeout(this.reset.bind(this), 0); // bind to 'this' }; Game.prototype.reset = function(){ this.clearBoard(); // ahhh, back in the context of the right 'this'! }; This could be rewritten as Game.prototype.restart = function () { this.clearLocalStorage(); this.timer = setTimeout(this.clearBoard.bind(this), 0); // bind to 'this' }; It would still show an example where bind would help, because this.clearBoard by itself, when passed as an argument to a function, is resolved before invocation, and when invoked has the same context as an ordinary function, which is a problem if Game.prototype.clearBoard also refers to this inside its own code. The difference is that in the example as written, leaving off bind would lead to a known error, that window.clearBoard is not a function, while in my rewritten example, this.clearBoard might not throw an error but would instead create and affect global variables, rather than members of the instance you extracted the method from.
James Edward Lewis
The example at the end of #1 should be rewritten to get at the heart of the matter: Game.prototype.restart = function () { this.clearLocalStorage(); this.timer = setTimeout(this.reset.bind(this), 0); // bind to 'this' }; Game.prototype.reset = function(){ this.clearBoard(); // ahhh, back in the context of the right 'this'! }; This could be rewritten as Game.prototype.restart = function () { this.clearLocalStorage(); this.timer = setTimeout(this.clearBoard.bind(this), 0); // bind to 'this' }; It would still show an example where bind would help, because this.clearBoard by itself, when passed as an argument to a function, is resolved before invocation, and when invoked has the same context as an ordinary function, which is a problem if Game.prototype.clearBoard also refers to this inside its own code. The difference is that in the example as written, leaving off bind would lead to a known error, that window.clearBoard is not a function, while in my rewritten example, this.clearBoard might not throw an error but would instead create and affect global variables, rather than members of the instance you extracted the method from.
Sergey Batishchev
Nope. Luckily this leak only applied to DOM-JS circular links (which were at the time modelled with COM): https://msdn.microsoft.com/en-us/library/dd361842%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
Sergey Batishchev
Nope. Luckily this leak only applied to DOM-JS circular links (which were at the time modelled with COM): https://msdn.microsoft.com/en-us/library/dd361842%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396
brianN2
Hopefully! :)
brianN2
Hopefully! :)
MikeL
Like the others have said, logical operators in Javascript takes advantage of the fact that JS has the concept of truthy and falsy to return the actual values (since they're all either truthy or falsy) rather than an actual boolean. That's why it's so common to see expressions like: !!x (double negation) which converts any value into an actual boolean. It's frequently used because developers like real booleans even though it's rarely necessary in JS.
MikeL
Like the others have said, logical operators in Javascript takes advantage of the fact that JS has the concept of truthy and falsy to return the actual values (since they're all either truthy or falsy) rather than an actual boolean. That's why it's so common to see expressions like: !!x (double negation) which converts any value into an actual boolean. It's frequently used because developers like real booleans even though it's rarely necessary in JS.
MikeL
On #9, I think you (almost) left out the most significant problem with passing a string to the setTimeout function: If you pass a function, that function will be invoked in the scope it was defined in (the same as the call to setTimeout if it's an anonymous function as in your example) but if you pass a string it will be parsed into a function and invoked in the global scope. You hint at this problem with the msgValue variable but I think it's the main argument against passing a function body as a string. Doing that wouldn't even be possible if msgValue was anything non-serializable.
MikeL
On #9, I think you (almost) left out the most significant problem with passing a string to the setTimeout function: If you pass a function, that function will be invoked in the scope it was defined in (the same as the call to setTimeout if it's an anonymous function as in your example) but if you pass a string it will be parsed into a function and invoked in the global scope. You hint at this problem with the msgValue variable but I think it's the main argument against passing a function body as a string. Doing that wouldn't even be possible if msgValue was anything non-serializable.
englishextra
Very nice. Especially on strict mode.
englishextra
Very nice. Especially on strict mode.
Oren Zomer
[2,3,10].sort() gives [10,2,3] due to string comparison... Does any other programming language do that?
Oren Zomer
[2,3,10].sort() gives [10,2,3] due to string comparison... Does any other programming language do that?
Michael Simkin
[ 2, 3, 10 ].sort( (a, b) => a - b )
Michael Simkin
[ 2, 3, 10 ].sort( (a, b) => a - b )
Oren Zomer
Yes, I know this is the right way sort an array of numbers - but for developers who are used to other languages like Python, where numbers are sorted correctly by default (and mixed-type list sorting places numbers before strings), it is not trivial to understand that sort() without a comparison function will compare the string values...
Oren Zomer
Yes, I know this is the right way sort an array of numbers - but for developers who are used to other languages like Python, where numbers are sorted correctly by default (and mixed-type list sorting places numbers before strings), it is not trivial to understand that sort() without a comparison function will compare the string values...
Michael Simkin
Yeh! I was surprised too.
Michael Simkin
Yeh! I was surprised too.
Michel H.
Good post! Thanks!
Michel H.
Good post! Thanks!
Jair Humberto
Seems that any anonymous functions will always be in the global context, not only in setTimeout's like functions.
Jair Humberto
Seems that any anonymous functions will always be in the global context, not only in setTimeout's like functions.
Vladimir Vakhromeev
Try to use Number.isNaN() instead of just isNaN(). https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
Vladimir Vakhromeev
Try to use Number.isNaN() instead of just isNaN(). https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Number/isNaN
Dmitri Pavlutin
Nice post, thanks. JavaScript becomes more and more popular. At first look it seems simple, but it's an illusion. Anyone looking to pass the mistake #1 (this keyword) can check <a href="http://rainsoft.io/gentle-explanation-of-this-in-javascript/">this article</a>. To pass #4 (equality) can check <a href="http://rainsoft.io/the-legend-of-javascript-equality-operator/">this one</a>.
Dmitri Pavlutin
Nice post, thanks. JavaScript becomes more and more popular. At first look it seems simple, but it's an illusion. Anyone looking to pass the mistake #1 (this keyword) can check <a href="http://rainsoft.io/gentle-explanation-of-this-in-javascript/">this article</a>. To pass #4 (equality) can check <a href="http://rainsoft.io/the-legend-of-javascript-equality-operator/">this one</a>.
rameramwe
i love you .. you're awesome this line saved my life var self = this ;
rameramwe
i love you .. you're awesome this line saved my life var self = this ;
Khaled Monsoor
isn't this something that they call "premature optimizations" !?
Khaled Monsoor
isn't this something that they call "premature optimizations" !?
bdiscus
Thanks, a year later and I can agree with you.
bdiscus
Thanks, a year later and I can agree with you.
Kálmán Kéri
The point here is reference counting GC can't free cycles of references while copying, compacting and mark-and-sweep collectors can. Generally, it has nothing to do with a particular language unless its specification prescribes what type of GC should be used. Regarding Javascript, here is a clarifying article. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management#Garbage_collection
Kálmán Kéri
The point here is reference counting GC can't free cycles of references while copying, compacting and mark-and-sweep collectors can. Generally, it has nothing to do with a particular language unless its specification prescribes what type of GC should be used. Regarding Javascript, here is a clarifying article. https://developer.mozilla.org/en-US/docs/Web/JavaScript/Memory_Management#Garbage_collection
finnich
Loved the post.....very informative for students learning languages this mistakes will help you to command language !!!!
finnich
Loved the post.....very informative for students learning languages this mistakes will help you to command language !!!!
Anand Siddharth
That's the reason why typescript comes to existence.
Anand Siddharth
That's the reason why typescript comes to existence.
Deadpool
We get it. You hate Javascript. But maybe it's not Javascript's fault, and you're just a poor developer? After "10+ years programming," why have you not transitioned to a strongly-typed language like Java? Seriously, your complaining just makes you look like an idiot.
Deadpool
We get it. You hate Javascript. But maybe it's not Javascript's fault, and you're just a poor developer? After "10+ years programming," why have you not transitioned to a strongly-typed language like Java? Seriously, your complaining just makes you look like an idiot.
Deadpool
I'm not trying to sound cool. Javascript has its downfalls, but those are highly outweighed by its perks and capabilities.
Deadpool
I'm not trying to sound cool. Javascript has its downfalls, but those are highly outweighed by its perks and capabilities.
Deadpool
Wait... you're calling me a "fuckwitted idiot," because I don't know your work history? Well, you're a fuckwitted idiot, if you don't know what color shoes I'm wearing right now! See how ridiculous that is? My response doesn't make me look like a noob. YOUR responses make you look like some jaded ass clown who wants to sound cool by bashing Javascript. It's funny you mention PHP, because Javascript is the new PHP where it's oh-so-fun to bash on it, because it "is the worst language." Go ahead and keep jumping on the bandwagon. If you hate Javascript so much, then why are you using it? Are you just that shitty of a Java developer?
Deadpool
Wait... you're calling me a "fuckwitted idiot," because I don't know your work history? Well, you're a fuckwitted idiot, if you don't know what color shoes I'm wearing right now! See how ridiculous that is? My response doesn't make me look like a noob. YOUR responses make you look like some jaded ass clown who wants to sound cool by bashing Javascript. It's funny you mention PHP, because Javascript is the new PHP where it's oh-so-fun to bash on it, because it "is the worst language." Go ahead and keep jumping on the bandwagon. If you hate Javascript so much, then why are you using it? Are you just that shitty of a Java developer?
Humphrey Pietersen
I found myself using Array.from(NodeList).forEach(item, index),... pretty often these days. I reckon it works as you say. Saves alot of lines. I couldnt believe how really little code i wrote to achieve a nice tabMenu...Lol
Humphrey Pietersen
I found myself using Array.from(NodeList).forEach(item, index),... pretty often these days. I reckon it works as you say. Saves alot of lines. I couldnt believe how really little code i wrote to achieve a nice tabMenu...Lol
John Peter
Great article. Beginners need to look at this. Same as this 7 mistakes every JavaScript developer should avoid!!! (https://www.spericorn.com/7-mistakes-every-javascript-developer-should-avoid/)
John Peter
Great article. Beginners need to look at this. Same as this 7 mistakes every JavaScript developer should avoid!!! (https://www.spericorn.com/7-mistakes-every-javascript-developer-should-avoid/)
Heena Kwag
Thank you for the great article! I would like to ask you for permission to translate this article into Korean and publish it on a company run blog (https://ui.toast.com/) and on our Github wiki page (https://github.com/nhn/fe.javascript). I will quote the original source and in no way use it to gain any monetary value. Please let me know what you think, and hope you have a great day :)
Heena Kwag
Thank you for the great article! I would like to ask you for permission to translate this article into Korean and publish it on a company run blog (https://ui.toast.com/) and on our Github wiki page (https://github.com/nhn/fe.javascript). I will quote the original source and in no way use it to gain any monetary value. Please let me know what you think, and hope you have a great day :)
Elias Hasle
Nice article! :-) #5: Why deepcopy the created fragment instead of just appending it? Surely that too will waste (and memory, if one is not careful), unless you need to add many of the same. #6 is solved by "let" instead of "var" on the counter. No need for a closure.
Elias Hasle
Nice article! :-) #5: Why deepcopy the created fragment instead of just appending it? Surely that too will waste (and memory, if one is not careful), unless you need to add many of the same. #6 is solved by "let" instead of "var" on the counter. No need for a closure.
Sutapa Mondal
Brilliant posts!!
Sutapa Mondal
Brilliant posts...Really very helpful.
John Weiss
<code> this.timer = setTimeout(this.reset.bind(this), 0); // bind to 'this'</code> So complicated! Why is this style better than the simple `self = this`?
Olivia Wilson
#3 doesn't cause memory leak, anything inside function will be collected by GC.
fighting mr
can I translate it into Chinese and post it?
Rodrigo
The first example for memory leak doesn't work anymore. To fix it, you can remove the unused function and just add a console.log to the original thing in some method. The original thing is in the closure, sure, but I think the browser got smarter and can tell you are not using it. Also, the unused function seems to be irrelevant.
comments powered by Disqus