19

Top Mistakes JavaScript Developers Make

 4 years ago
source link: https://flatlogic.com/blog/top-mistakes-javascript-developers-make/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

JavaScript is a programming language that allows you to implement complex features on web pages and, to cut a long story short, you have already known a lot about JS since it is the most popular programming language in 2019 (it’s not our opinion, all figures we got from Developer Survey 2019 from Stackoverflow). If you don’t hear of this survey you should take a look, while we continue our introduction. 

Since JavaScript is the basis of any web application, we are not going to discuss JS benefits or a list of JS possibilities. Instead, we will show you some typical mistakes that almost every JS programmer has made during his career.

flatlogic-templates.jpeg

In Flatlogic we create web & mobile application templates built withReact, Vue ,Angular andReact Native to help you develop web & mobile apps faster. Go and check out yourself!

See our themes!

According to the same Stackoverflow survey, 41% of programmers that took part in the survey have less than five years of professional coding experience.

Screen-Shot-2019-12-30-at-10.58.38-AM-1024x574.pngImage source: https://insights.stackoverflow.com/survey/2019#overview

This article is mostly for those developers. New developers (0-2 years) may find examples from the article useful because it’s a bad code you can learn from. More experienced developers (3 + years) may get a smile by recognizing the mistakes you have made in the past. Anyway spending some time reading this article gives you either knowledge or fun. Enjoy reading!

The list of mistakes:

  • Do you remember the difference between «=», «==»  and «===»?
  • Forgetting about the scope of variables.
  • Misunderstanding the difference between “let”, “const”  and “var”.
  • Incorrect references to instance methods.
  • Difficulties of using this.

Do you remember the difference between «=», «==»  and «===»?

Odds are you first encountered the problem with code like this:

var x = 1;
if (x = 7) { 
  alert("Hello"); 
} else {
  alert("Nope");
}

And you get “Hello”! Why? The answer is very simple: you don’t understand the difference between the 3 operators mentioned above. It’s not a complicated mistake, and once you learn it you will not likely forget it. Since this mistake is very simple, you can overlook it when it comes to conditions of jumping out of a loop.

Let’s get this thing over with and go further:

“=” is the equal operator, so it’s used for assignment. In our example, we assign seven to “x” in the condition and get words of welcome “Hello”.

The correct code looks like this:

var x = 1;
if (x == 7) {
  alert("Hello");
} else {
  alert("Nope");
}

We get “Nope”.

“==” is the loose equality comparison operator. Why loose? Because it allows converting values from one type to another to compare them. Even if we assign a string value “7” to x, and compare it with number value “7” the code returns to us “Hello”. However, the code below returns “Nope”:

Why? Because “===” is the strict equality comparison operator. If this operator returns “true” it means that our values are identical both in value and in type. There is an analog for “===” – the method Object.is. It has some differences in the processing of -0, +0 and NaN values, but some of you know what these differences are, while others can turn to JavaScript Guide . And in general, it’s a good practice: 

If you have any doubts about JS methods or features, you can always google it, but we highly recommend to use JavaScript Guide.

Forgetting about the scope of variables

Another quite simple mistake:

let arr = [1,2,3,4,5,6,7];
var j;
for (j=0;  j < arr.length; j++) {
  console.log (arr[j]);
} 
// …some long code
console.log ( j ); // we get the number “7”

And it’s easy to forget that our variable changes its value after the loop. This mistake exists not only in the JS community but in general. In some languages, you define a variable only within a loop, and it’s destroyed once the loop ends, but not in JavaScript.

And the opposite situation, when you try to get access to a variable that was defined within their local scope (it refers to Function scope). Example:

function myFunction() {
  var me = "You can't touch me!";
} 
console.log(me);

“me” is not defined, sorry, you can contact your lawyer or just remember the scope of variables in JavaScript. The correct code is:

var me;
function myFunction() {
  me = "You can't touch me!";
}
console.log(me + ‘I Can, sorry’);

Another example since JS update in 2015, and the keyword let came to JS to declare variables (ECMA Script 6) is: 

let arr = [1,2,3,4,5,6,7];
for (let j = 0; j < arr.length; j++) {
  console.log(arr[j]); // the output: 1, 2, 3, 4, 5, 6, 7
} 
console.log(j) // j = 0.

The keyword let didn’t change the variable “j” compared to the first example. And this question is the topic of our next abstract

Misunderstanding the difference between “let”, “const”  and “var”

It’s closely related to the previous problem, but since almost everybody googled “the difference between var , const and let ” we separate this question. Let’s first look at the code below:

console.log(x); // undefined
var x = 5;
console.log(x); // the output is 5

The code is logical as the output, no questions.  Another example:

console.log(x); // Error: cannot access “x” before the initialization
let x = 5;
console.log(x);

The reason is that var is function scoped and let is block scoped. When you declare a variable with let keyword, they are moved to the beginning of the block. This may lead to a reference error when you try to access the variable before the initialization.

It’s called “temporary dead zone”, if you want to know more information about it, you can visit an official web site for JS developers Mozilla JavaScript Guide .

But we move on with our next participant and show an example to describe everything:

let a = 5;
var b = 10;
const c = 11;
 
if (a === 5) {
  let a = 4; 	// The scope is inside the if-block
  var b = 1; 	// The scope is global
  const c = 15; // The scope is inside the if-block
  
  console.log(a);   // 4, 
  console.log(b);   // 1
  console.log(c);   // 15
} 
console.log(a);  // 5, the value changes to the initial 
console.log(b);  // 1, the value from if-block saves
console.log(c);  // 11, the value changes to the initial

And the last code for this chapter:

a = 10; 	// it’s OK, the value of a is changed to 10
b = 20; 	// it’s OK, the value of b is changed to 20
c = 7; 		// SyntaxError: Identifier "c" has already beed declared 
const c = 15; 	// The same error

What happened? In “if block” we declared “a” and “c” variables in if-block and changed the value of a global variable “b”. Outside the block “a” and “C” returned to its initial values. After that, we tried to change the values of all variables: let and  var allow us to do that, while  const returned an error. The reason is that the  const declares a read-only reference to a value within a certain scope (it may be local or global). That’s why we managed to declare the new value of the “C” variable in if-block but failed to change the value outside of it.  

Incorrect references to instance methods

Let’s create a new object and use the prototype property of a function to add “ whoAmI ” method. Then create an instance “ obj” of our object (the code below):

var MyObject = function() {}
MyObject.prototype.whoAmI = function() { 
  console.log(this === window ? "window" : "MyObj"); 
}
var obj = new MyObject();

The preparatory phase ended, let’s start to make our life simpler: since we need to get access to a recently established method and we want to make it simple, so let’s create a reference to it and check if it works properly.

obj.whoAmI(); // MyObj
var anotherMethod = obj.whoAmI;
anotherMethod(); // window

And we get the output “window” instead of expected “MyObj”.

Why? Well, when we create a reference var anotherMethodobj . whoAmI , method  whoAmI has been defined in the global scope. A global scope is a window object in a browser, so the keyword  this becomes equal to the window, not the instance of  MyObject . If we want to make a correct reference to an instance method, then we need to call this method from the object itself or make a reference to the object, but not just to the method of the object.

The right reference will look like this:

var obj = new MyObject(); 
var anotherObj = obj;
anotherObj.whoAmI() // MyObj

or

obj.link = obj.whoAmI
obj.link(); // MyObj

And we get the equal result finally.

Difficulties of using this

JavaScript has become quite a complicated language. This is a keyword in JavaScript the value of which is evaluated during the run-time, depending on the context. 

function myFunction() {
  var myObject = {
     objProperty: "some text",
     objMethod: function() {
        alert(objProperty);
        }
     }
  myObject.objMethod();
} 
myFunction();

And we get ReferenceError: objProperty is not defined. Functions defined on a JavaScript object accessing properties on that JavaScript object and failing to use this reference identifier. The correct code looks like this (not our  this =)):

function myFunction() {
  var myObject = {
     objProperty: "some text",
     objMethod: function() {
        alert(this.objProperty);
        }
     }
  myObject.objMethod();
}
myFunction();

The idea is simple: when myObject . objMethod is called, this becomes myObject during the call of objMethod . When we define an object and want to access its properties and methods, we need to access the object itself first. (sounds logical) But there are also reverse situations when this is used incorrectly.

Game.prototype.restart = function () {
  this.clearLocalStorage();
  this.timer = setTimeout(function() {
    this.clearBoard(); 
  }, 0);
}

It returns to us another error: undefined is not a function.

The point is that this in  this . clearBoard() line is unnecessary here because when you invoke  setTimeout() you work with  window . setTimeout() , so you invoke the window object in the browser. The object window doesn’t have a  clearBoard() method. The correct form will look like this:

Game.prototype.restart = function () {
  var self = this;
  this.clearLocalStorage();
  this.timer = setTimeout(function() {
    self.clearBoard(); // this = window
  }, 0);
}

And an example that has existed since EcmaScript2015 was released:

Game.prototype.restart = function () {
  this.clearLocalStorage();
  this.timer = setTimeout(() => {
    this.clearBoard(); // this = Game
  }, 0);
}

That also became possible after ECMAScript 6. When we use an arrow function, we stay in the scope of the previous function without creating a new local scope.

You might also like these articles:


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK