📜 ⬆️ ⬇️

10 oddities and secrets of JavaScript

Javascript At the same time frightening and attractive. I am sure that if Pablo Picasso was a programmer, he created this language. Null here is an object, an empty array, it is false, and functions fly next to it like tennis balls.



The target audience of the article are advanced developers who want to learn more about JavaScript. This is a collection of weird and well-kept secrets. The secrets of some chapters may be useful to you when developing your own software products, others are just subjects for laughter and condemnation. In any case, we begin!
')

Data Types and Ads


1. Null is an object

Let's start with the well-known strangeness. Null - the object, and the highest of them. Null? An object? “This cannot be, because null is the complete absence of any value, ” you say. And you are undoubtedly right. However, be that as it may, I have proof. Here it is:

alert (typeof null); // 'object' 


Despite this, null is not an object instance. (If you did not know, the values ​​in JavaScript are instances of the base object. Each number is an instance of the Number object, each object is an instance of the object object, and so on.) This returns the mind, because null is the absence of a value , which means it cannot be an instance of -or. So the following line displays false:

 alert (null instanceof Object); //false 


2. NaN is a number

Are you surprised that null is an object? Then think about this — NaN (“Not a Number” is not a number) is a number! The further, the worse! NaN is not even equal to itself. (Does your head still hurt?)

 alert (typeof NaN); // 'Number' alert (NaN === NaN); // false 


In fact, NaN is not equal to anything at all. The only way to compare something with NaN is the isNaN () function.

3. Array without keys == false (or about the truth and the curve)

Here's another odd javascript:

 alert (new Array() == false); // true 


To understand what is happening here, you have to accept the concept of truthy and falsy. There are “lite” kinds of true and false that can let you down if you delve into logic and philosophy.

I have read a lot of definitions of what truth and krivdochka are, and the simplest, in my opinion, sounds like this: in JavaScript, every object has a built-in boolean value that is called when an object should behave like a boolean; for example, when you compare it to false.

Since apples cannot be compared with pearls, when JavaScript calls for comparison of objects of different types, it performs their conversion to a common type. False, zero, null, undefined, empty lines and NaN - everything is reduced to false - not permanently, but only in the context of this expression. Here is an example:

 var someVar = 0; alert (someVar == false); // true 


Here we request a comparison of the number 0 and the value false. Since the data is not of the same type, JavaScript implicitly converts their values ​​to the values ​​of the built-in boolean flags, which (in the case of zero) is equal to the curve.

You may have noticed that I did not include empty arrays in the list of objects that result in false. They behave very interestingly - they are calculated as truth, but, when compared with a boolean value, they behave like a curve. Are you still alive? Good, because I have prepared one more example for you:

 var someVar = []; //  alert (someVar == false); // true if (someVar) alert ('hello'); // 'hello',  someVar  true 


To avoid casting, you can use the type and value comparison operator === (instead of ==, which only compares values.)

 var someVar = 0; alert (someVar == 0); //  true, 0 -  alert (someVar === false); //  false, 0 - ,     


Fuh. As you already understood, type casting in JavaScript is a rather complicated topic, so you should devote a couple more nights to the study of this topic.

You can discuss this question with me here (eng.) Or, if you are already ready enough, you can read the exact casting process, it is described in the documentation .

Regular expressions


4. The replace () method can accept a callback function.

This is one of the most secret secrets of JavaScript, it came to us in version 1.3. Most replace uses use something like this:

 alert('10 13 21 48 52'.replace(/d+/g, '*')); //    * 


This is a simple replacement, the number - an asterisk. But what if we want to be able to choose the place to replace? What if we want to replace only those numbers that are less than 30? This can be achieved using the same replace method. We just have to call the callback function on every match:

 alert('10 13 21 48 52'.replace(/d+/g, function(match) { return parseInt(match) < 30 ? '*' : match; })); 


For each match, JavaScript will call our function, passing our match as a parameter. Then, we will return an asterisk (if the number is less than 30) or the parameter is unchanged.

5. Regular expressions - more than find and replace

Many advanced JavaScript developers use only match and replace when working with regular expressions. But JavaScript gives us more options than just 2 methods.

Of greatest interest is test (), which works as a match, but does not return a match, it simply checks the occurrence of the pattern in the string.

 alert (/\w{3,}/.test('Hello')); // 'true' 


The code above searches for 3 or more alphanumeric characters in the string, and since the Hello string meets these requirements, we get true. We do not need a coincidence, only the result.

Also, the RegExp object, with which you can create dynamic regular expressions, is the opposite of static. This gives an advantage in the form of a short record (we just surrounded the pattern with slashes). But, in this case, you cannot point to variables, so creating dynamic patterns is impossible. With RegExp () you can do it

 function findWord(word, string) { var instancesOfWord = string.match(new RegExp('\b'+word+'\b', 'ig')); alert(instancesOfWord); } findWord('car', 'Carl went to buy a car but had forgotten his credit card.'); 


Here we create a dynamic pattern that is based on the value of the word argument. The function returns the number of the word word in the string (not part of another word). So, our example will return car once, ignoring this word in Carl and card. We do this with the b flag.

Since RegExp is defined as a string, and not with a short syntax, we can use variables when constructing a pattern. This means that we must double-escape any special characters, as we did with the word boundary symbol.

Functions and contexts



6. You can fake context

The context in which something is executed determines which variables are available. Free JavaScript (one that is not launched from a function) operates on the global context of the window object, to which everything has access, and local variables that are declared inside the function are available only inside this function, not outside.

 var animal = 'dog'; function getAnimal(adjective) { alert(adjective+' '+this.animal); } getAnimal('lovely'); // 'lovely dog'; 


In this example, our variable and function are declared in a global context. Since it always points to the current context, in this example it points to the window. Therefore, when the function looks for window.animal, it finds it. It's okay for now. But, we can make our function think that it runs in a different context, despite the native context. We can do this using the call () method, not using a function.

 var animal = 'dog'; function getAnimal(adjective) { alert(adjective+' '+this.animal); }; var myObj = {animal: 'camel'}; getAnimal.call(myObj, 'lovely'); // 'lovely camel' 


Here, our function is called not in the context of a window, but in the context of myObj as an argument to the call () method. Call () pretends that the function is a method myObj. Notice that any arguments that we pass to call () after the first one will be passed to the function.

I heard developers who said that they have been programming for many years and have never used it because this is abnormal code behavior. Although it is quite interesting.

By the way, apply () does the same work as call (), except that the arguments are passed as an array. Here is an example:

 getAnimal.apply(myObj, ['lovely']); //   


7. Functions can call themselves

Nothing forbids this:

 (function() { alert('hello'); })(); // 'hello' 


The syntax is very simple: we declare a function and immediately call it like other functions, using parentheses. You may ask: “Why do we need to use it?” It may look like a mismatch of terms: a function usually contains the code we want to execute later, not now, otherwise we do not put it into a function.

One of the advantages of self-executing instructions (FIC) is the use of the current values ​​of variables within the pending code. Here is the problem:

 var someVar = 'hello'; setTimeout(function() { alert(someVar); }, 1000); var someVar = 'goodbye'; 


Newbies on the forums ask why alert displays goodbye, not hello. The answer is that the value of the variable someVar is not calculated before running the code. And by that time, the variable is already overwritten by the value goodbye.

FIC give the opportunity to solve this problem. Instead of using a timeout callback , we return it from the AIS , to which we pass the current value of the variable as an argument. This means that we pass and isolate the current value of the variable, protecting it from what happens to the real variable someVar. This is how to make a photo of the car before repainting, the photo will not be updated, it will always show the color of the car at the time of taking the photo.

 var someVar = 'hello'; setTimeout((function(someVar) { return function() { alert(someVar); } })(someVar), 1000); var someVar = 'goodbye'; 


Now, we see hello, as we wanted, because the function shows an isolated version of the variable.

Browser


8. Firefox reads and returns colors in RGB, not in HEX.

I could never understand why Mozilla does this. Of course, I have to show an example:

 Hello, world! <script> var ie = navigator.appVersion.indexOf('MSIE') != -1; var p = document.getElementById('somePara'); alert(ie ? p.currentStyle.color : getComputedStyle(p, null).color); </script> 


When most browsers return ff9900, Firefox returns the rgb (255, 153, 0) equivalent. There are functions that convert RGB to HEX.

As you can see, IE has other methods for determining computed styles.

Additionally


9. 0.1 + 0.2! == 0.3

This oddity is found not only in JavaScript, it is a problem of the whole computer science. The conclusion will be the same - 0.30000000000000004.

This problem is called computer inaccuracy. When JavaScript executes a string, it translates the values ​​into their binary equivalent.

This is where the problem starts - 0.1 not 0.1 in binary equivalent, but close to this value. This is how to translate text from Russian into Belarusian. It seems, but not the same.

The rest is beyond the scope of this article (we have no mathematical circle here)

This topic is widely discussed in computer science and development forums. You can offer your own solutions to this problem.

10. Indefinite can be determined

Well, let's end with stupidity. It sounds strange, but undefined is a non-reserved word in JavaScript, although it has a special meaning — to show that the variable is not defined.

 var someVar; alert(someVar == undefined); // true 


So far, so good. But:

 undefined = "I'm not undefined!"; var someVar; alert(someVar == undefined); // false! 


You can refer to the list of all reserved javascript words .

Source: https://habr.com/ru/post/171359/


All Articles