JavaScript is considered a beginner friendly language. This is partly because of its widespread use on the Internet, and partly because it has features that make it possible to write imperfect code and still work (it’s not as strict as many other languages, and you don’t have to suffer with semicolons or memory management).

In this article, we’ll cover some interesting JavaScript issues.

1. Why is math.max () less than math.min ()?

The fact that math.max () > math.min () returns false sounds ridiculous, but it’s actually kind of interesting.

If no argument is given, math.min () returns infinity and math.max () returns -infinity. This is just part of the specification for Max () and min() methods, but there is good logic behind it. To see why, take a look at the code:

MathMin (1)/ / 1
MathMin (1, infinity)/ / 1
MathMin (1- infinity),// - infinite
Copy the code

If -infinity is supposed to be the default argument to math.min (), then every result is infinity, which makes no sense! If the default argument is infinity, adding any other arguments will return that number — which is exactly what we want.


2. Why does 0.1 + 0.2 === 0.3 return false?

In short, it has to do with how accurately JavaScript can store floating point numbers in binaries. If you enter the following formula in the Google Chrome console, you will get:

0.1 + 0.2
/ / 0.30000000000000004
0.1 + 0.2  -  0.2
/ / 0.10000000000000003
0.1 + 0.7
/ / 0.7999999999999999 ` ` `
Copy the code

This is unlikely to cause problems if you execute simple equations without requiring high precision. But if you need to test for equality, it can cause trouble even in simple applications. There are some solutions.

Fixed decimal point

For example, if you know the maximum precision required (for example, if you are dealing with currency), you can use the integer type to store the value. So for $4.99, you can store 499 and execute any equation. You can then display the result to the end user using an expression that results = (value / 100).tofixed (2) returns a string.

Decimal in binary code

If precision is important, another option is to use the binary-encoded decimal (BCD) format, which you can access in JavaScript using this BCD library. Each decimal value is stored in one byte (8 bits). This is inefficient because a byte can store 16 individual values, and the system only uses values 0-9. However, if accuracy is important to your application, it may be worth the trade-off.


Why is 018 minus 017 equal to 3?

Result 3 returned by 018-017 is the result of the default type conversion. In this case, we are talking about octal numbers.

An introduction to octal numbers

You know the use of base-2 and base-16 number systems in computing, but base-8 also has a prominent place in computer history: in the late 1950s and 1960s, it was used to abbreviate binary. Cut material costs in an expensive manufacturing system!

Soon after, the hexadecimal system (base-8) appeared.

Are octal numbers still useful?

Is octal useful in modern programming languages? For some use cases, Octal has an advantage over hexadecimal because it does not require any non-numeric digits (using 0-7 instead of 0-f).

One common use is file permissions on Unix systems, where there are eight permission variants:

4 2 1 0 – – No permission 1 – – x Execute only 2 – x – Write only 3 – XX write and execute 4 x – – Read only 5 x – x read and execute 6 xx – Read and write 7 XXX read, write and execute

It is also used in digital displays for similar reasons.

Back to the question

In JavaScript, the prefix 0 converts any number to octal. However, 8 is not used in octal, and any number 8 containing an is silently converted to a regular decimal number.

Therefore, 018 — 017 is actually equivalent to the decimal expression 18 — 15, because 017 is octal but 018 decimal.


4. What is the difference between a function expression and a function declaration?

Function declarations use the keyword function, followed by the name of the function. Instead, function expressions begin with the function name and assignment operator var, let, or const followed by the function name =. Here are some examples:

// Function Declaration
function sum(x, y) {
 return x + y
}
// Function Expression: ES5
var sum = function(x, y) {
 return x + y
}
// Function expression: ES6 +
constSum = (x, y) =>{return x + y }
Copy the code

In use, the key difference is that function declarations are promoted, while function expressions are not. This means that the JavaScript interpreter moves the function declaration to the top of its scope, so you can define the function declaration and call it anywhere in the code. By contrast, you can only call function expressions in linear order: you must define them before calling them.

Today, many developers prefer functional expressions for several reasons:

  • First, function expressions enforce a more predictable structured code base. Of course, structured code bases can also use declarations; It simply declares that it allows you to get rid of messy code more easily.
  • Second, we can use ES6 syntactic function expressions: this is generally more succinct, let and const to provide more control over whether a variable can be reassigned or not, as we’ll see in the next problem.

5. What’s the difference between var, let and const?

Var is a variable declaration keyword in the first version of JavaScript. But its shortcomings have led to the adoption of two new keywords in ES6: let and const.

I) distribution

The basic difference is that both let and var can reassign const. This is the best choice for const variables that do not need to change, and it protects against errors such as accidental reallocation. Note that const allows variables to vary, which means that if it represents an array or an object, they can change. You cannot reassign the variable itself.

Both let and VAR can be reassigned, but — because the following points should be made clear — let has significant advantages over VAR, making it a better option in most cases, such as not timely saving variables that need to be changed in all cases.

Ii) Variable promotion

Similar to the difference between function declarations and expressions (described above), variables that use declarations are always promoted to the top of their respective scopes, whereas variable declarations are promoted to const and let, but if you try to access them before they are declared, you will get a “temporary dead zone” error. This is useful behavior because VAR can be more error-prone, such as accidental reallocation. See the following example:

varX = "global scope";function foo(a){
  varX = "functional scope"console.log (X)} FOO ()/ / "functional scope"
consoleLog (x)/ / "global scope"
Copy the code

In this case, the result foo() is what we expect console.log(x) to be. But what if we put down the second var?

var x = "global scope"

function foo() {
  x = "functional scope"
  console.log(x)
}

foo(); // "functional scope"
console.log(x) // "functional scope"
Copy the code

Although defined within a function, x = “functional scope” overrides global variables. We need to repeat the keyword var to specify that the scope of the second variable x is limited to foo().

Iii) Scope

While var is function scoped, let and const are block scoped: normally, a block is any code {} inside curly braces, including functions, conditional statements, and loops. To illustrate the difference, look at the following code:

var a = 0
let b = 0
const c = 0

if (true) {
  var a = 1
  let b = 1
  const c = 1
}

console.log(a) / / 1
console.log(b) / / 0
console.log(c) / / 0
Copy the code

In our condition block, global-scoped var a has been redefined, but global-scoped let b and const c have not. In general, ensuring that local assignments remain local will make your code cleaner and less buggy.


6. What if you specify variables without keywords?

What if you define variables without using keywords? Technically, if x is not defined, then x = 1 is a shorthand for window.x = 1. This is a common cause of memory leaks.

To avoid this, you can use strict mode (introduced in ES5). By writing Use Strict at the top of the document or in a specific function. Later, when you try to declare a variable without a keyword, you will receive an error: Uncaught SyntaxError: Unexpected Indentifier.


7. What is the difference between OOP and FP?

JavaScript is a multi-paradigm language, meaning that it supports many different programming styles, including event-driven, functional, and object-oriented.

There are many different programming paradigms, but the two most popular styles in contemporary computing are functional programming (FP) and object-oriented programming (OOP) — and JavaScript can perform both at the same time.

Object-oriented programming (OOP)

OOP is based on the concept of objects. These are data structures that contain data fields — called “properties” in JavaScript — and “methods.”

Some of JavaScript’s built-in objects include Math (for methods such as Random, Max, and sin), JSON (for parsing JSON data), and primitive data types such as String, Array, Number, and Boolean.

Whenever you rely on built-in methods, stereotypes, or classes, you are actually using object-oriented programming.

Functional programming (FP)

FP is based on the concept of “pure functions” that avoid shared state, mutable data, and side effects. This may seem like a lot of terminology, but you’ve probably already created a lot of pure functions in your code.

Given the same input, a pure function always returns the same output. It has no side effects: these are anything other than returning results, such as logging to the console or modifying external variables.

As for shared state, here’s a simple example where state can change the output of a function even if the input is the same. Let’s set up a scenario with two functions: one for adding a number by 5 and one for multiplying by 5.

constNum = {val:1
}
constAdd5 = () => num. Val + =5
constMultiply5 = () => num. Val * =5
constMultiply5 = () => num. Val * =5
Copy the code

If add5 calls the first multiply5, the overall result is 30. But if we call the function the other way around and record the result, we get something different: 10.

This violates the principle of functional programming, because the results of functions vary depending on context. We can rewrite the above code so that the results are predictable:

constNum = {val:1
}
constAdd5 = () =>Object.assign ({}, num, {val: num. Val +5})constMultiply5 = () =>Object.assign ({}, num, {val: num. Val *5}
Copy the code

Now, num. Val is always 1, and add5(num) or multiply5(num) always yields the same result regardless of context.

8. What is the difference between imperative and declarative programming?

We can also consider the difference between OOP and FP in terms of the difference between “command” and “declarative” programming.

These are general terms that describe the characteristics shared between many different programming paradigms. FP is an example of declarative programming, while OOP is an example of imperative programming.

In a basic sense, imperative programming is about how you do something. It illustrates the most important methods, steps, and features for and while loops, if and switch expressions, and so on.

const sumArray = array= > {
  let result = 0
  for (let i = 0; i < array.length; i++) {
    result += array[i]
  }
  return result
}
Copy the code

Declarative programming, by contrast, focuses on what to do and abstracts away how to rely on expressions. This generally results in cleaner code, but on a scale, debugging becomes more difficult because it is much less transparent.

The sumArray() function is short for:

const sumArray = array= > { return array.reduce((x, y) = > x + y) }
Copy the code

9. What is prototype-based inheritance?

Finally, let’s look at prototype-based inheritance. There are several different styles of object-oriented programming, and JavaScript uses Prototype-based inheritance. The system allows repetitive behavior by using existing objects that act as “prototypes.”

Even if the idea of prototyping is new to you, you will encounter prototyping systems by using built-in methods. For example, use functionality to manipulate all methods on array.prototype-based objects like Map, Reduce, splice, etc. In fact, each instance of an Array(defined using square brackets [], or using new Array()) inherits array.prototype, which is why methods like map, reduce, and splice are available by default.

Similarly, almost all other built-in objects, such as Strings and Booleans: only a few, such as Infinity, NaN, NULL, and undefined, have no properties or methods.

At the end of the prototype chain, we find Object.prototype, almost every Object in JavaScript is an object. prototype: Array.prototype and String.prototype instances, both of which inherit the properties and methods of Object.prototype.

To add properties and methods to an object using prototype syntax, simply call the object as a function and then use the prototype keyword to add properties and methods:

function Person() {}
Person.prototype.forename = "John"
Person.prototype.surname = "Smith"
Copy the code

Should we override or extend the behavior of the prototype?

You can change the behavior of built-in prototypes just as we create and extend our own, but most developers (and most companies) would advise against it.

If you want multiple objects to share the same behavior, you can always create a custom object (or define your own “class” or “subclass”) that inherits from the built-in stereotype without making any changes to the stereotype itself. If you plan to work with other developers who have certain expectations of the default behavior of JavaScript, editing this default behavior can easily lead to errors.

It’s worth noting, however, that not everyone is so opposed to this extension of built-in archetypes. For example, see this article by Brendan Eich, creator of JavaScript. In this article (from 2005), Eich suggests that the prototype system is actually partially built – to make scaling possible!