The author has recently done a sort of native JS knowledge, will post the whole process, content details as far as possible to cover all JS knowledge points, at the same time there will be a continuous progress of the process. After all, JS is the root of front-end ER, and it is not too much to learn again. This series of JS beginners will have a great harvest, at the same time to the intermediate developers will have a very good promotion, senior developers will be reviewed and consolidated, it is suggested that the collection of irregularly back to see.

First, data types

There are seven basic data types (the last two are newly added in ES6) :

  • string
  • number
  • boolean
  • null
  • undefined
  • symbol
  • bigint

Reference data types are divided into basic reference types and collection reference types:

  • Date
  • RegExp
  • Math

Collection reference types:

  • Object
  • Array
  • Function
  • Set
  • WeakSet
  • Map
  • WeakMap

Primitive types are the simplest data, and reference types are objects made up of multiple values. When assigning a value to a variable, the JS engine needs to confirm whether the value is the original value or a reference value, since it is the actual value stored in the variable that is being manipulated. A reference value is an object that is stored in memory. When you declare an object to a variable, you are actually referring to the object. Var obj = {a:1}; var obj = {a:1}; var obj2 = obj; obj.a = 2; At this point you’ll notice that obj2.a also changes to 2. Understanding this is important for understanding collection reference types, as we’ll see later.

Variables and declarations

Js supports var, let, const, function, import declarations, or importing variable keywords.

Var declaration

Prior to ES6, the var keyword was used to declare raw data. It has the following characteristics

//* Declare scope *//
function msg(){
  var a = 1; // Local variables
}
msg();
console.log(a);  / / an error
Copy the code
//* declare promotion *//
function msg(){
  console.log(a);
  if(false) {var a = 1;
  }
}
msg();  // undefined
Copy the code

Execution of the above code does not report an error, because JS scans the current code before execution, automatically promoting the declared variable to the top of the current scope. The above methods are equivalent to

function msg(){
  var a;
  console.log(a);
  if(false){
   a = 1; }}Copy the code

Note: Variable promotion also exists in the function declaration method.

2. Let declaration

Let is similar to var, but with a very significant difference. Let is block-scoped and cannot be accessed outside the scope of let declarations. There is no variable promotion and an error is reported if you attempt to access it without declaring it. This is a “temporary dead zone”. Features:

  • There is no variable prompt
  • Temporary dead zone
  • Duplicate declarations are not allowed in the same scope
if(true) {console.log(a);  / / an error
  let a = 1;
  let a = 2;  / / an error
}
console.log(a);  //Uncaught ReferenceError: a is not defined
Copy the code

Const declaration

Const behaves much the same as let, with the following properties:

  • Declare a read-only constant. Once declared, its value cannot be changed.
  • Once declared, it must be assigned, otherwise an error is reported;

Note: The limitation of a const declaration applies only to references to the variable to which it refers. That is, if a const variable refers to compound data such as an object or array, it is not against the rules to change the internal properties of the data.

Judgment of data type

1, universal judgment method

function getType(va){
  return Object.prototype.toString.call(val)
}
// There are about the following types
var typeList = [
  "[object String]"."[object Number]"."[object Null]"."[object Undefined]"."[object Boolean]"."[object Symbol]"."[object BigInt]"."[object HTMLHtmlElement]"."[object Arguments]"."[object Math]"."[object Date]"."[object Object]"."[object Array]"."[object Set]"."[object WeakSet]"."[object Map]"."[object WeakMap]",]Copy the code

2. Typeof judgment method

Basic data types: In addition to null, can be determined using Typeof.

typeof 2;  // number
typeof 'a';  //string
typeof false;  // boolean
typeof undefined;  // undefined
typeof Symbol('1');  // symbol
typeof BigInt(10);  // bigint
Copy the code

Compound: returns object except Function;

typeof [];  // object
typeof new Object(a);// object
Copy the code

Can typeof not be used to determine data types? The answer is yes, but in some other combination.

// Determine whether the object is an object
function getType(val){
  return typeof val === 'object' && val.constructor === Object
}
// Check whether it is an array
function getType(val){
  return typeof val === 'object' && val.constructor === Array
}
/* Other complex data and so on */
Copy the code

On the premise of excluding objects, instanceof method can also be used to judge. Instanceof is based on a stereotype chain query that returns true whenever it is in the stereotype chain. One caveat, however, is that Object is the top layer of all prototype chains, which is easy to overlook

[] instanceof Array;  // true
[] instanceof Object; // true
Copy the code

If a variable val instanceof Array returns true, it does not necessarily mean val is an Array!

3, Array. IsArray ()

Native JS built-in methods that are specifically used to determine whether an array is an array

var arr = [];
Array.isArray(arr);  // true
Copy the code

4. How to implement one manuallyinstanceofmethods

The Instanceof method works by looking up the prototype chain until null.

function myInstanceof(from,to){
  // If null or the primary data type, return false
  if(from= = =null || typeof from! = ='object') return false;
  var _proto = Object.getPrototypeOf(from);  // Returns the prototype chain of the instance prototype
  while(_proto){
    // Find the top layer
    if(_proto === null) return false;
    if(_proto === to.prototype) return true
    _proto = Object.getPrototypeOf(_proto); }}Copy the code

5,nullWhy not objects?

Typeof determines whether a variable is object with the exception of null. Because NULL is clearly a basic data type, it does not return NULL as expected. Why is this so? Because: This is caused by a bug in JS. Even though typeof NULL returns object, it is not an object. JS in the original version of the use of 32-bit system, null into computer readable binary all zeros, and the object is exactly the beginning of 000, so null is also mistakenly considered as object.

Operators and statements

1. Unary operator

Operators that operate on only one value are called unary operators. Unary operators are ++ and –, with the difference between pre and post. Before ++ is to add and then use, after ++ is to use and then add. The same is true for operators.

var num = 0;
console.log(num++);  // Print the result as 0, in which case num changes to 1
console.log(++num);  // Print the result as 2, in which case num changes to 2
console.log(--num);  // The output is 1, and the num value changes to 1
console.log(num--);  // The print result is 1, and the num value changes to 0
Copy the code

2. Additive operators

The additive operators are the addition and subtraction operators. In JS, conversion of different data types occurs when two values are added or subtracted.

1+1; / / 2
"1"+1;  / / "11"[] + {};// "[object Object]"[] +1;  / / "1"{} +1;  / / "1"
new Set() +1;  // "[object Set]1"
NaN + NaN;  // NaN
"1"+NaN;  // "1[NaN]"
Copy the code

If one of the operands is a string, the following rule applies:

  • If both operands are strings, concatenate the second string to the first;
  • If only one operand is a string, the other operand is converted to a string and the two strings are concatenated.

If any of the operands are objects, values, or booleans, their toString() method is called to get the string, and the previous string rules apply. For undefined and null, the String() function is called to get “undefined” and “null”, respectively. ———— from JavaScript Advanced Programming, 4th Edition

3. Equality operator

Mainly divided into equal == and congruent ===, and vice versa! = and! = = =. The former performs a type conversion and then a comparison, while the latter ensures that the types are equal in addition to verifying that the values are equal. The equality and inequality operators follow the following rules when converting operand types.

  • If any of the operands is a Boolean, it is converted to a value and then compared for equality. False converts to 0 and true converts to 1.
  • If one of the operands is a string and the other is a value, it tries to convert the string to a value and then compares for equality.
  • If one operand is an object and the other is not, the valueOf() method of the object is called to get its original value, which is then compared according to the previous rules.

When comparing, the two operators follow the following rules.

  • Null is equal to undefined.
  • Null and undefined cannot be converted to other types of values for comparison.
  • If any of the operands is NaN, the equality operator returns false and the inequality operator returns true. Remember: Even if both operands are NaN, the equality operator returns false because NaN is not equal to NaN by rule.
  • If both operands are objects, they are compared to see if they are the same object. The equality operator returns true if both operands refer to the same object. Otherwise, the two are not equal.
null= =undefined;  // true
"NaN"= =NaN;       // false
5= =NaN;           // false
NaN= =NaN;         // false
NaN! =NaN;         // true
false= =0;         // true
true= =1;          // true
true= =2;          // false
undefined= =0;     // false
null= =0;          // false
"5"= =5;           // true
Copy the code

———— from JavaScript Advanced Programming Edition 4 Object type equality operation Conversion rules If one of the values of the equality operator is an object type, it is executed in the following order until it is converted to the original type.

  • If there isSymbol.toPrimitive()Method, this method is called first;
  • callvalueOf()Method, if cast to a raw numeric type, returns the result;
  • calltoString()Method attempts to convert to a raw numeric type;
  • If neither of them returns the original numeric type, an error is reported;

The congruent operators === and the incongruent operators! == They are similar to the equality operator, except that they are compared without operator type conversions, meaning that the type must be equal before and after the comparison to return true. Note: JS states that NaN are not equal at all times.

NaN= = =NaN;   // false
NaN= =NaN;   // false
Copy the code

Object.is() whereas the equality operator == and the congruence operator === have their own disadvantages. The former does an implicit conversion of the type, the latter NaN does not equal itself, and +0 equals -0. In ES6, the object. is method is introduced to compare whether two operators are equal, and it supports two parameters.

Object.is({},{});    // false
Object.is(NaN.NaN);  // true
Object.is(+0, -0);    // false
Copy the code

4. Loop statements

1. The do{}while() statement is similar to the while statement, except that it is written differently. When using the while condition, do not write an infinite loop to prevent memory overflow.

var i = 0;
do{
  console.log(i);
  i++
}while(i < 10);
// Prints the numbers from 0 to 9

while (i<20){
  i++;
  console.log(i)
}
Copy the code

This section describes how to exit the for loop. There are two main elements: continue to enforce the next loop immediately, and break to exit the current for loop immediately

for(var i=0; i<5; i++){if(i === 3) continue;
  console.log(i)
}
// Prints the result 0, 1, 2, 4

for(var i=0; i<5; i++){if(i===3) break;
  console.log(i)
}
// Prints 0, 1, 2
Copy the code

3. For in and for of statements for in: mainly used to obtain the key name, traversal all enumerable attributes; Supports traversal of strings, arrays, objects, etc. For of: used to obtain keys and traverse strings, arrays, sets, and maps. An error is reported if the iterator interface is deployed on the iterator object. Note that traversal of objects is not supported, for example {a:1,b:2} will result in an error

var obj = {a:1.b:2};
var arr = ['a'.'b'];
Copy the code
for(var key in obj){
  console.log(key)
}

// Print the result ['a','b']
for(var val of obj){
  console.log(val)
}
Uncaught TypeError: obj is not iterable

for(var key in arr){
  console.log(key)
}
// Prints the result 0 1

for(var val of arr){
  console.log(val)
}
// Print the result 'a' 'b'
Copy the code

Note:

  • for inWhen traversing the object, the prototype chain will be checked. If you want to accurately determine whether the current object contains corresponding attributes, you can useObject.hasOwnPropertyProperties;
  • It can also be used when obtaining object propertiesObject.keys()Methods;
  • for inorfor ofSymbol type data cannot be obtained because Symbol is not enumerable and can be used to judge SymbolObject.getOwnPropertySymbols()Methods;

4. A switch statement

Scope and memory

1. Passing of parameters in a function

Arguments to all functions in ECMAScript are passed by value. That is, every parameter that goes into the function, it gets copied. If the parameter is a basic data type, variables outside the function are not affected.

var num = 0;
function add(s){
  s += 1;
  console.log(s)
}
add(num);  // the result of s is 1
console.log(num);  The value of num is still 0
Copy the code

If the function parameters are compound data, it is possible to change the original data

var persion = {
  name:"wang".sex:"man"
}
function set(val){
  val.name = "li";
  val = {
    name:"zhang".sex:"women"
  }
  return val
}
var s = set(persion);
console.log(persion);  // {name:"li",sex:"man"}
console.log(s);  // {name:"zhang",sex:"women"}
Copy the code

Why is that? Because the set method is passed persion, the first sentence in the function changes the value of the name attribute outside the function. When the second statement is executed, the val variable refers to a newly created object, which the function then returns.

Scope and execution context

Execution context: Execution context is divided into global context, function context and block-level context. The context of variables or functions determines what data they can access and how they behave. When executing each piece of code, a context will be created first, and the variable value will be searched in the current context. If the variable value cannot be found, the outer stack will be searched until the global context. If it cannot be found, an error will be reported. The context is destroyed after code execution, while the global context is destroyed before exiting the program. Each function creates a context stack when it executes. After the function is executed, the context stack pops up the function context, returning control to the previous execution context. Each function is recycled after execution, unless its internal variables are referenced by another executing function, in which case the unreferenced variables are destroyed. In this case, a closure is generated. I understood the closure is: the current function have permission to access another scope within the scope of variables, namely, another function in the execution after the completion of the internal variables should be recycled destroyed, but because the currently executing function USES the current part variables, cause function internal part variables had not be destroyed. Scope chain: When trying to access a variable, the JavaScript interpreter looks in the current scope. If it doesn’t find a variable, it looks in the parent scope. If it doesn’t find a variable, it looks up the hierarchy until it reaches the global scope. As each function executes, it copies the parent scope to form a scope chain. This is where the essence of the closure comes in: there is a reference to the parent scope in the current environment.

3. How to use memory reasonably

  • Use closures wisely and set unnecessary variables tonull;
  • Avoid adding variables to the global scope, if necessary, after usedelete;

Six, some questions

1. Why doesn’t 0.1+0.2 equal 0.3?

console.log(0.1+0.2);  / / 0.30000000000000004
Copy the code

Internal computer use is binary, after converted into binary floating-point number 0.1 and 0.2 will be an infinite loop, and the program is digit limitation, can’t let it infinite loop, this time will be truncated binary precision loss, so after truncation of binary when added together and then converted to a decimal will appear error.

2. Implicit conversion of object attribute types

What does this code output?

var obj = {a:1};
var obj2 = {b:2};
obj[obj2] = 3;
obj[{c:3}] = 4;
console.log(obj[obj2]);
Copy the code

JavaScript object attributes are in string format; if they are not, implicit conversions occur. Obj [obj2] = 3; Obj2 calls toString to [object object], which is equivalent to obj[“[object object]”] = 3. So executing the fourth sentence is the same as executing the third sentence, so the answer is 4

3, [] ==! [] What was the result? Why is that?

If you read this article carefully, you will know the answer. The right hand side of the equals sign returns a Boolean value, which is implicitly converted to a numeric value for comparison. The Boolean value on the right is false, converted to a value of 0. The left empty array is converted to the value Number([]), which yields 0, so the final result is true

4. How data is stored in JavaScript memory

Generally speaking, the system divides two different memory Spaces: the stack and the heap. The basic data types are stored on the stack in a certain order. Reference data types are generally stored unordered in the heap, with no data structure, and data can be stored arbitrarily. The data structure in the stack has a lumpy smell, so every time a variable is copied to another variable, a new copy is made, thus completely disconnecting from the previous data. The data in the heap is out of order, and when you try to copy it out, it seems lazy, it doesn’t actually copy the whole heap, it just tells the variables that need to be copied to point to the current heap.

5. What is the result of the following code?

let a = 1;
let b = new Number(1);
let c = 1;
console.log(a == b);
console.log(a === b);
console.log(b === c);
Copy the code
function sum(a, b) {
  return a + b;
}
var result = sum(1.'2');
console.log(result);
Copy the code

The answer is simple, you can run the results yourself.