5 things most new to JavaScript don't understand

Hello! At the end of September, OTUS will launch a new stream of the Fullstack JavaScript Developer course. In anticipation of the start of classes, we want to share with you an author's article prepared especially for students of the course.



Article author: Pavel Yakupov







Preview I want to note right away that in this article topics that are familiar to “ninjas” are examined, and the article is aimed more at making beginners better understand some of the nuances of the language, and not be lost in the tasks that they often give during an interview - after all, such Tasks have nothing to do with real development, and those who give them, most often in this way try to understand how well you know JavaScript.









Reference memory types



How exactly is data stored in JavaScript? Many programming courses start explaining with the classic: a variable is a kind of “box” in which we store some data. Which ones, for languages ​​with dynamic typing, it seems like it doesn’t matter: the interpreter itself “swallows” any data types and dynamically changes the type if necessary, and you should not think about the types of variables and how they are processed. Which of course is wrong, and so we will begin today's discussion with features that often slip away: how variables are stored in JavaScript - in the form of primitives (copies) or in the form of links.



We will immediately list the types of variables that can be stored in the form of primitives: these are boolean



, null



, undefined



, Number



, String



, Symbol



, BigInt



. When we encounter separately declared variables with this data type, we must remember that during the initial initialization they create a memory cell - and that they can be assigned, copied, transferred and returned by value.



The rest of JavaScript relies on referenced memory areas. What are they needed for? The creators of the language tried to create a language in which memory would be used as economically as possible (and this was absolutely not new at that time). To illustrate, imagine that you need to remember the names of three new work colleagues - completely new names, and to enhance the comparison, your new colleagues from India or China with unusual names for you. Now imagine that your colleagues are called the same as you and your two best friends at school. In what situation will it be easier to remember? Here, the memory of a person and a computer works similarly. Here are some specific examples:



 let x = 15; //  x x = 17;//   console.log(x)//    //     let obj = {x:1, y:2} //   let obj1 = obj; //  obj  obj1 obj1.x = 2; //    "" console.log(obj1.x); //  ,   console.log(obj.x) //      obj.x ?
      
      





Thus, if you encounter a similar task during an interview, try to immediately understand what type of data is in front of you - where it came from and how it got the value, as a primitive type, or as a reference type.







Context work



In order to understand exactly how the context works in JS, you need to study a few points:



  1. Global / local level of visibility.
  2. The difference in context when initializing variables in the global / local scope.
  3. Arrow functions.


Once upon a time, back in ES5 everything was quite simple: there was only a variable declaration using var, which when declared in the program flow was considered global (which meant that the variable was assigned as a property to a global object, such as window



or global



). Then let



and const



came to the scene, who behave somewhat differently: they are not assigned to the global object, and are stored in memory differently, focusing on the block scope. Now var is already considered obsolete, because its use can lead to clogging of the global scope, and in addition, let



looks much more predictable.



1. So, for understanding it is worthwhile to clearly understand what are the scope in JavaScript (scope). If a variable is declared in the global scope using the let



directive, then it is not assigned to the window



object, but is saved globally.



Let's move on to the tasks that most often beginners get on the context of the interview.



 //:     ? let x = 15; function foo(){ let x = 13; return x; } console.log(x)// 15     foo(); console.log(x)//     x = foo(); console.log(x)//    return   ,   
      
      





2. At the same time, not all beginners are aware of how the JavaScript interpreter reads the code: in fact, it reads it twice, the first time it reads the code of functions declared as Function Declaration (and is ready to execute them at the second, real reading and execution ) Another small trick is related to var



and let



: the first time a variable with the var



directive is read, it is set to undefined



. But with let



its premature call is not possible at all:



 console.log(x); console.log(y) var x = 42; let y = 38; //   ? //   undefined  error!
      
      





3. The arrow functions that appeared in ES6 quickly gained popularity - they were quickly adopted by programmers on Node.js (due to a quick update of the engine) and React (due to the features of the library and the inevitable use of Babel). With respect to context, arrow functions adhere to the following rule: they do not bind to this



. We illustrate this:



 var x = 4; var y = 4; function mult(){ return this.x * this.y; } let foo = mult.bind(this); console.log(foo()); let muliply = ()=>x*y; console.log(muliply()); /*           x  y     let,  function declaration       */
      
      









Data Types and What Applies To



Let's say right away: an array is essentially an object, and in JavaScript this is not the first variation of an object - Map, WeakSet, Set, and collections confirm this.



So, an array is an object, and its difference from a regular object in JS is primarily in greater speed due to optimization of indexing, and secondly in inheritance from Array.prototype, which provides a larger set of methods, which’s why Big Brother » Object.prototype



.



 console.log(typeof({})) console.log(typeof([])) console.log(typeof(new Set)) console.log(typeof(new Map)) //        
      
      





Next in the queue of oddities in data types is null



. If you ask JavaScript what type of data null is, we get a fairly unambiguous answer. However, here it will not do without some tricks:



 let x = null; console.log(typeof(x)); //! , null   objet, ? console.log(x instanceof Object.prototype.constructor); //false //   !      )
      
      





It is worth remembering that null



is a special data type - although the beginning of the previous example pointed strictly to another. For a better understanding of why this particular type was added to the language, it seems to me that it is worth exploring the basics of C ++ or C # syntax.



And of course, in interviews one often comes across such a task, whose peculiarity is related to dynamic typing:



 console.log(null==undefined);//true console.log(null===undefined);//     false
      
      





A large number of tricks are associated with type casting when comparing in JS; we are not physically able to bring them all here. We recommend referring to “What the hell JavaScript” .







Illogical features left in the language during the development process



Addition of lines. In fact, the addition of lines with numbers cannot be attributed to errors in the development of the language, however, in the context of JavaScript, this led to well-known examples that are considered not logical enough:



codepen.io/pen/?editors=0011



 let x = 15; let y = "15"; console.log(x+y);//  "" console.log(xy); //       
      
      





The fact that plus simply adds lines with numbers is relatively illogical, but you just need to remember this. This may be especially unusual because the other two interpreted languages ​​that are popular and widely used in web development - PHP and Python - do not throw such tricks with addition of strings and numbers and behave much more predictably in such operations.



Similar examples are less known, for example, with NaN:



  console.log(NaN == NaN); //false console.log(NaN > NaN); //false console.log(NaN < NaN); //false …   ... ,      NaN? console.log(typeof(NaN)); // number
      
      





Often NaN brings unpleasant surprises if, for example, you incorrectly configured type checking.



The example with 0.1 +0.2 is much more famous - because this error is related to the IEEE 754 format, which is also used, for example, in such a “mathematical” Python.



We also include a lesser known bug with the Epsilon number, the reason for which lies in the same vein:



 console.log(0.1+0.2)// 0.30000000000000004 console.log(Number.EPSILON);// 2.220446049250313e-16 console.log(Number.EPSILON + 2.1) // 2.1000000000000005
      
      







And questions that are slightly more complicated:



 Object.prototype.toString.call([])//    ? // ->  '[object Array]' Object.prototype.toString.call(new Date) //     Date? // -> '[object Date]'   
      
      









Event Processing Stages



Many beginners do not understand browser events. Often even unfamiliar are the most basic principles by which browser events work - interception, ascent, and default events. The most mysterious thing from the point of view of a beginner is the emergence of an event that, no doubt, is justified at the beginning raises questions. Ascent works as follows: when you click on a nested DOM element, the event fires not only on it, but also on the parent, if a handler with such an event was also installed on the parent.

In the event that an event comes up, we may need to cancel it.



 //    ,      function MouseOn(e){ this.style.color = "red"; e.stopPropagation(); //    }
      
      





In addition, for beginners it is often a problem to cancel events that occur by default. This is especially important when developing forms - because form validation, for example, needs to be done both on the client side and on the server side:



codepen.io/isakura313/pen/GRKMdaR?editors=0010



 document.querySelector(".button-form").addEventListener( 'click', function(e){ e.preventDefault(); console.log('    . ,  ') } )
      
      





Canceling an event’s surfacing can also bring some troubles: for example, you can create a so-called “dead zone” in which the necessary thing will not work - for example, an event of an element that is “not lucky” to be near.



Thank you all for your attention! Here are some useful links from which you can draw a lot of useful information:





References
learn.javascript.ru

developer.mozilla.org/en/docs/Web/JavaScript/Reference

learn.javascript.ru/event-bubbling

learn.javascript.ru/bind#reshenie-2-privyazat-kontekst-s-pomoschyu-bind

medium.com/@KucherDev/ when- and why- is it worth- to use-arrow-functions-es6-3135a973490b

github.com/denysdovhan/wtfjs/blob/master/README.md

habr.com/en/company/otus/blog/456124

habr.com/en/company/mailru/blog/335292

habr.com/en/company/otus/blog/457616

habr.com/en/company/otus/blog/456724



That's all. We are waiting for you at the free webinar , which will be held on September 12.



All Articles