Recently, I have arranged the high frequency test questions on the front face and shared them with you to learn. If you have any questions, please correct me!
Note: 2021.5.21 has been updated to modify some errors in this article. Add a mind map, according to their own interview experience and the interview on the platform such as Niuker.com, the frequency of the interview questions will be roughly divided, can be targeted to review.
The following is a series of articles.
[1] “2021” high frequency front face test summary HTML article
[2] “2021” high-frequency front end of the CSS section
[3] 2021
[4] 2021
[5] “2021”
[6] “2021”
【7】 “2021” High-Frequency front end test questions summary
[8] “2021” high frequency front end test questions summary
[9] “2021” high frequency front end test question summary of computer network article
[10] “2021” high frequency front end test summary of browser principles
[11] the performance optimization of “2021” high frequency test paper summary
[12] “2021” high frequency front end of the handwritten code of the test summary
[13] “2021” high frequency front end test summary code output results
1. Data types
1. What are the data types in JavaScript and what are their differences?
There are eight data types in JavaScript: Undefined, Null, Boolean, Number, String, Object, Symbol, and BigInt.
Symbol and BigInt are new data types in ES6:
- Symbol represents a unique and immutable data type that is created to resolve possible conflicts with global variables.
- BigInt is a type of numeric data that can represent integers in any precision format. Using BigInt allows you to safely store and manipulate large integers, even if they are outside the range of safe integers that Number can represent.
The data can be divided into raw data types and reference data types:
- Stack: raw data type (Undefined, Null, Boolean, Number, String)
- Heap: Reference data types (objects, arrays, and functions)
The difference between the two types lies in the storage location:
- The original data type is a simple data segment directly stored in the stack. It occupies a small space and has a fixed size. It is frequently used data, so it is stored in the stack.
- Reference data type stored in the heap object, large space, size is not fixed. If stored on the stack, the performance of the program will be affected. The reference data type stores a pointer on the stack to the starting address of the entity in the heap. When the interpreter looks for a reference value, it first retrieves its address in the stack and then retrieves the entity from the heap.
The concepts of heap and stack exist in data structures and operating system memory. In data structures:
- In the data structure, data in the stack is accessed in the first and last way.
- The heap is a priority queue and is sorted by priority, which can be specified by size.
In an operating system, memory is divided into a stack area and a heap area:
- The stack memory is automatically allocated and freed by the compiler to store function parameter values, local variable values, and so on. It operates in a similar way to a stack in a data structure.
- The heap memory is usually allocated and freed by the developer. If the developer does not free it, it may be reclaimed by the garbage collection mechanism at the end of the program.
2. What are the methods of data type detection
(1) the typeof
console.log(typeof 2); // number
console.log(typeof true); // boolean
console.log(typeof 'str'); // string
console.log(typeof []); // object
console.log(typeof function(){}); // function
console.log(typeof {}); // object
console.log(typeof undefined); // undefined
console.log(typeof null); // object
Copy the code
Array, object, and NULL are all judged as objects, and all other judgments are correct.
(2) instanceof
Instanceof can correctly determine the type of an object, and its internal mechanism is to determine whether a prototype of that type can be found in its prototype chain.
console.log(2 instanceof Number); // false
console.log(true instanceof Boolean); // false
console.log('str' instanceof String); // false
console.log([] instanceof Array); // true
console.log(function(){} instanceof Function); // true
console.log({} instanceof Object); // true
Copy the code
As you can see, instanceof can only correctly determine the reference data type, not the base data type. The instanceof operator can be used to test whether an object has a constructor’s prototype property in its prototype chain.
(3) the constructor
console.log((2).constructor === Number); // true
console.log((true).constructor === Boolean); // true
console.log(('str').constructor === String); // true
console.log(([]).constructor === Array); // true
console.log((function() {}).constructor === Function); // true
console.log(({}).constructor === Object); // true
Copy the code
Constructor has two functions. One is to determine the type of data, and the other is to access the constructor of an object through a constrcutor object. Note that constructor cannot be used to determine data types if an object is created to change its prototype:
function Fn(){};
Fn.prototype = new Array(a);var f = new Fn();
console.log(f.constructor===Fn); // false
console.log(f.constructor===Array); // true
Copy the code
(4) the Object. The prototype. ToString. Call ()
Object. The prototype. ToString. Call use the Object prototype method toString () to determine the data type:
var a = Object.prototype.toString;
console.log(a.call(2));
console.log(a.call(true));
console.log(a.call('str'));
console.log(a.call([]));
console.log(a.call(function(){}));
console.log(a.call({}));
console.log(a.call(undefined));
console.log(a.call(null));
Copy the code
Call the toString method is also a test Object obj, obj. The toString () and Object. The result of the prototype. ToString. The result of the call (obj), is this why?
This is because toString is the prototype method of Object, and types such as Array, function, and so on, which are instances of Object, override the toString method. (Function returns a string containing the body of the function, Array returns a string composed of elements…) Instead of calling the toString method on Object (which returns the specific type of the Object), using object.tostring () does not give you the Object type, but converts obj to a string type. Therefore, when you want to get the specific type of an Object, you should call the toString method on the Object stereotype.
3. Determine the types of arrays
- Through the Object. The prototype. ToString. Call () to do judgment
Object.prototype.toString.call(obj).slice(8, -1) = = ='Array';
Copy the code
- Judge by the prototype chain
obj.__proto__ === Array.prototype;
Copy the code
- Use the Array. IsArray () of ES6 to make the judgment
Array.isArrray(obj);
Copy the code
- Judge by instanceof
obj instanceof Array
Copy the code
- Through the Array. The prototype. IsPrototypeOf
Array.prototype.isPrototypeOf(obj)
Copy the code
4. Difference between null and undefined
First of all, Undefined and Null are both basic data types. Each of these basic data types has only one value, that is, Undefined and Null.
Undefined means undefined, and null means empty. Normal variables that are declared but not yet defined will return undefined. Null is primarily used to assign values to variables that may return objects as initialization.
Undefined is not a reserved word in JavaScript, which means it is possible to use undefined as a variable name, but doing so is dangerous because it affects the judgment of the value of undefined. There are ways to get a safe undefined value, such as void 0.
Null typing returns “object” when using Typeof for these two types, which is a historical problem. Returns true when two types of values are compared using double equals signs, and false when three equals signs are used.
5. What is the result of typeof null and why?
The result of typeof null is Object.
In the first version of JavaScript, all values were stored in 32-bit cells, each containing a small type label (1-3 bits) and the actual data for which the value was being stored. Type labels are stored in the low position of each cell and there are five data types:
000: object - The currently stored data points to an object.1: int - The data currently stored is a31A bit signed integer.010: double - The currently stored data points to a double floating-point number.100: string - The currently stored data points to a string.110: Boolean - The data currently stored is a Boolean value.Copy the code
If the lowest value is 1, the length of the type tag flag bit is only one bit. If the lowest bit is 0, the length of the type label flag bit is three bits, providing an additional two bits for storing the other four data types.
There are two special data types:
- The value of undefined is (-2)30(a number outside the integer range);
- The value of null is a machine code null pointer (null Pointers are all zeros).
That is to say, null has a type tag of 000, which is the same as Object’s type tag, so it is determined to be Object.
6. Intanceof operator implementation principle and implementation
The instanceof operator determines whether the constructor’s prototype property appears anywhere in the object’s prototype chain.
function myInstanceof(left, right) {
// Get the prototype of the object
let proto = Object.getPrototypeOf(left)
// Get the constructor's prototype object
let prototype = right.prototype;
// Determine whether the constructor's prototype object is on the prototype chain of the object
while (true) {
if(! proto)return false;
if (proto === prototype) return true;
// If no prototypeof Object is found, the Object. GetPrototypeOf method is used to retrieve the prototypeof the specified Object
proto = Object.getPrototypeOf(proto); }}Copy the code
7. Why 0.1+0.2! == 0.3, how to make it equal
In the development process encountered a problem like this:
let n1 = 0.1, n2 = 0.2
console.log(n1 + n2) / / 0.30000000000000004
Copy the code
This is not the desired result, to be equal to 0.3, convert it:
(n1 + n2).toFixed(2) // Note that toFixed is rounded
Copy the code
The toFixed(num) method rounds Number to the Number in the specified decimal place. So why is this happening?
Computers store data in binary, so when a computer calculates 0.1+0.2, it’s actually calculating the binary sum of the two numbers. 0.1 binary is 0.0001100110011001100… (1100 cycles), the binary of 0.2 is: 0.00110011001100… (1100 cycles), the binary of both numbers are infinite cycles. So how does JavaScript deal with infinite loop binaries?
Generally we think of numbers as both integers and decimals, but in JavaScript there is only one type of Number: Number, which is implemented in accordance with the IEEE 754 standard and uses 64-bit fixed length, the standard double floating-point Number. In the binary scientific representation, the decimal part of a double precision floating point number can only retain 52 digits at most, plus the first 1, in fact, retain 53 significant digits, the rest need to be abandoned, in accordance with the principle of “rounding 0 to 1”.
According to this principle, adding the binary numbers of 0.1 and 0.2 and converting them to decimal is 0.30000000000000004.
So let’s seeHow are the doubles saved:
- Part 1 (blue) : stores the sign bit, which is used to distinguish positive and negative numbers. 0 represents a positive number and occupies one bit
- Part 2 (green) : stores the exponent and takes up 11 bits
- The third part (red) is used to store a fraction, occupying 52 bits
For 0.1, its binary is:
0.00011001100110011001100110011001100110011001100110011001 10011..Copy the code
To scientific notation (the result of scientific notation is floating point numbers) :
1.1001100110011001100110011001100110011001100110011001*2^ -4
Copy the code
We can see that the sign bit of 0.1 is 0, the exponent bit is -4, and the decimal place is:
1001100110011001100110011001100110011001100110011001
Copy the code
So once again, if the exponent bit is negative, how do you store it?
The IEEE standard specifies an offset that is added to the exponent each time, so that even if the exponent is negative, the offset will be positive. Since JavaScript numbers are double precision numbers, the exponential part of the double is 11 bits, and the range of representation is 0 to 2047. The OFFSET of the IEEE fixed double is 1023.
- When the exponential bits are not all zeros and not all ones (normalized values), IEEE states that the order code calculation formula is e-BIAS. In this case, the minimum value of E is 1, then 1-1023= -1022, and the maximum value of e is 2046, then 2046-1023=1023. As you can see, the range of values in this case is
- 1022 ~ 1013
. - When the exponent bits are all zeros (non-normalized values), IEEE states that the order code is calculated by 1-BIAS, i.e., 1-1023= -1022.
- When the exponent bits are all 1’s (special value), IEEE specifies that the floating-point number can be used to represent three special values, which are plus infinity, minus infinity, and NaN. Specifically, when the decimal place is not 0, it means NaN; When the decimal place is 0, the sign bit s=0 means positive infinity, and when s=1 means negative infinity.
For the above 0.1, the exponent bit is -4, -4+1023 = 1019. The binary is 1111111011.
Therefore, 0.1 is expressed as:
0 1111111011 1001100110011001100110011001100110011001100110011001
Copy the code
With that said, it’s time to start with the question, how to achieve 0.1+0.2=0.3?
A straightforward solution to this problem is to set a margin of error, often referred to as “machine accuracy.” In JavaScript, this value is usually 2-52. In ES6, the Number.EPSILON property is provided, and its value is 2-52, just check whether 0.1+0.2-0.3 is less than Number. 0.1+0.2 ===0.3
function numberepsilon(arg1,arg2){
return Math.abs(arg1 - arg2) < Number.EPSILON;
}
console.log(numberepsilon(0.1 + 0.2.0.3)); // true
Copy the code
8. How do I get a safe undefined value?
Since undefined is an identifier, it can be used and assigned as a variable, but this affects the normal judgment of undefined. The expression void ___ returns no value, so undefined is returned. Void does not change the result of an expression, just that the expression does not return a value. So we can use void 0 to get undefined.
9. What is the result of Typeof NaN?
NaN means “not a number,” and NaN is a sentinel value (regular value with special purpose) used to indicate error conditions in numeric types, i.e., “a mathematical operation did not succeed, and this is the result returned after failure.”
typeof NaN; // "number"
Copy the code
NaN is a special value that is not equal to itself and is the only value that is not reflexive. NaN! == NaN is true.
10. What is the difference between isNaN and number. isNaN?
- The function isNaN receives an argument and attempts to convert it to a numeric value. Any value that cannot be converted to a numeric value will return true. Therefore, non-numeric values passed in will return true, affecting the determination of NaN.
- The number. isNaN function first determines whether the passed parameter is a Number. If it is a Number, it continues to determine whether it is a NaN.
11. Rules for casting the == operator?
In the case of ==, if the types of the two sides of the comparison are different, a cast is performed. If x and Y are the same, the following judgment process will be carried out:
- First, it determines whether the types are ** the same. If they are ** the same, it compares the size of the two.
- If the type is different, it will be cast;
- They’re going to see if they’re comparing
null
和undefined
If it is, it will returntrue
- Check whether the two types are
string
和number
If it is, it will convert the string tonumber
1= ='1'
↓
1= =1
Copy the code
- Determine whether one of the parties is
boolean
If it is, it willboolean
tonumber
And then judge
'1'= =true
↓
'1'= =1
↓
1= =1
Copy the code
- Determine whether one of the parties is
object
And the other party isstring
,number
orsymbol
If it is, it willobject
Convert to the original type and then judge
'1'= = {name: 'js'} left'1'= ='[object Object]'
Copy the code
The flowchart is as follows:
12. Rules for converting other values to strings?
- Null and Undefined, Null is converted to “Null”, Undefined is converted to “Undefined”,
- Boolean: true converts to “true”, false converts to “false”.
- Values of type Number are converted directly, but small and large numbers are used in exponential form.
- The value of type Symbol is directly converted, but only explicit casts are allowed. Using implicit casts produces an error.
- Defined for ordinary objects, unless the toString () method, or you will call the toString () (Object. The prototype. The toString () to return the internal properties of [[Class]] value, such as “[Object Object]”. If the object has its own toString() method, that method is called and its return value is used when it is stringed.
13. Rules for converting other values to numeric values?
- The value of Undefined is converted to NaN.
- A value of type Null is converted to 0.
- A value of type Boolean. True converts to 1 and false converts to 0.
- String values are converted as if they were converted using the Number() function. If they contain non-numeric values, they are converted to NaN, and empty strings are 0.
- The value of type Symbol cannot be converted to a number.
- Objects (including arrays) are first converted to the corresponding primitive type value, and if a non-numeric primitive type value is returned, it is then cast to a number following the above rules.
To convert a value to a valueOf the corresponding primitive type, the abstract operation ToPrimitive first checks (through the internal operation DefaultValue) to see if the value has a valueOf() method. If it has and returns a value of a primitive type, it is cast using that value. If not, the return value of toString(), if present, is used for casting.
If neither valueOf() nor toString() returns a base type value, TypeError is generated.
14. Rules for converting other values to Boolean values?
The following values are false: • undefined • null • false • +0, -0 and NaN • “”
A Boolean cast of a false value results in false. Logically, everything outside the list of false values should be true.
15. | | and && operator returns a value?
&& and | | first judgment can be carried to the first operand condition, if it is not a Boolean value is the mandatory converted to Boolean type, and then execute condition judgment.
- For | |, if the condition judgment result to true will return the value of the first operand, if to false will return the value of the second operand.
- Am&, on the other hand, returns the second operand if true, and the first if false.
&& and | | return values of them one of the operands, and unconditioned judgment result
16. What is the difference between object.is () and the comparison operators “===” and “==”?
- If two equal signs (==) are used to determine whether the two types are the same, the two types are forcibly converted and then compared.
- Return false if the type of the three equals sign (===) is different from the type of the three equals sign (===).
- When using object. is for equality, it is generally the same as for trials. it handles some special cases where -0 and +0 are no longer equal, and two Nans are equal.
17. What are wrapper types in JavaScript?
In JavaScript, primitives have no properties or methods, but to make it easier to manipulate the values of the primitives, JavaScript implicitly converts the values of the primitives to objects behind the scenes when a property or method is called. For example:
const a = "abc";
a.length; / / 3
a.toUpperCase(); // "ABC"
Copy the code
When accessing ‘ABC ‘.length, JavaScript converts’ ABC’ to a String(‘ ABC ‘) in the background, and then accesses its length property.
JavaScript can also explicitly convert a base type to a wrapper type using the Object function:
var a = 'abc'
Object(a) // String {"abc"}
Copy the code
You can also reverse the wrapper type to the basic type using the valueOf method:
var a = 'abc'
var b = Object(a)
var c = b.valueOf() // 'abc'
Copy the code
Take a look at what the following code prints:
var a = new Boolean( false );
if(! a) {console.log( "Oops" ); // never runs
}
Copy the code
The answer is nothing, because even though the wrapper’s basic type is false, false becomes an object when it’s wrapped as a wrapper type, so its non-value is false, so the contents of the body of the loop don’t run.
18. How to do implicit type conversions in JavaScript?
First, I’ll introduce the ToPrimitive method, which is implicit in every value in JavaScript to convert a value (whether a primitive type value or an object) to a primitive type value. If the value is of a basic type, the value itself is returned. If the value is an object, it looks something like this:
/ * * *@obj The object to be converted *@type Expected result type */
ToPrimitive(obj,type)
Copy the code
The value of type can be number or string.
(1) When type is number, the rules are as follows:
- call
obj
thevalueOf
Method, if raw, return, otherwise next; - call
obj
thetoString
Methods, follow as above; - throw
TypeError
The exception.
(2) When type is string the rules are as follows:
- call
obj
thetoString
Method, if raw, return, otherwise next; - call
obj
thevalueOf
Methods, follow as above; - throw
TypeError
The exception.
As you can see, the main difference is the order in which toString and valueOf are called. By default:
- If the object is a Date object
type
The default isstring
; - In other cases,
type
The default isnumber
.
To summarize the above rule, for objects other than Date, the general rule for converting to basic types can be summarized as a function:
var objToNumber = value= > Number(value.valueOf().toString())
objToNumber([]) === 0
objToNumber({}) === NaN
Copy the code
Implicit conversions in JavaScript occur mostly between +, -, *, /, and ==, >, and <. These operators can only operate on basic type values, so the first step before performing these operations is to ToPrimitive the values on both sides to the basic type, and then perform the operation.
Here are the rules for implicit conversions of primitives with different operators (for objects, they are converted to primitives by ToPrimitive, so the primitives conversion rules will eventually apply) :
+
The operator
When there is at least one string variable on either side of the + operator, both variables are implicitly converted to strings; In other cases the variables on both sides are converted to numbers.
1 + '23' / / '123'
1 + false / / 1
1 + Symbol(a)// Uncaught TypeError: Cannot convert a Symbol value to a number
'1' + false // '1false'
false + true / / 1
Copy the code
-
,*
,\
The operator
NaN is also a number
1 * '23' / / 23
1 * false / / 0
1 / 'aa' // NaN
Copy the code
- for
= =
The operator
Convert the values on both sides of the operator to number as much as possible:
3= =true // false, 3 converts number to 3, true converts number to 1
'0'= =false //true, '0' converts number to 0, false converts number to 0
'0'= =0 // Convert '0' to '0'
Copy the code
- for
<
and>
Comparison operators
If both sides are strings, compare the alphabetical order:
'ca' < 'bd' // false
'a' < 'b' // true
Copy the code
In other cases, convert to a number and compare:
'12' < 13 // true
false > -1 // true
Copy the code
This is an implicit conversion of the base type, and the object is converted to the base type by ToPrimitive and then converted:
var a = {}
a > 2 // false
Copy the code
The comparison process is as follows:
a.valueOf() // {}}, as mentioned above, the default type of ToPrimitive is number, so valueOf first, the result is still an object, next
a.toString() // "[object object]" is now a string
Number(a.toString()) // NaN, according to the above < and > operator rules, to convert to a number
NaN > 2 //false to get the comparison result
Copy the code
Such as:
var a = {name:'Jack'}
var b = {age: 18}
a + b // "[object Object][object Object]"
Copy the code
The operation process is as follows:
a.valueOf() // {}}, as mentioned above, the default type of ToPrimitive is number, so valueOf first, the result is still an object, next
a.toString() // "[object Object]"
b.valueOf() / / in the same way
b.toString() // "[object Object]"
a + b // "[object Object][object Object]"
Copy the code
19. +
When is an operator used for concatenation of strings?
According to the ES5 specification, + concatenates if an operand is a string or can be converted to a string by following the steps below. If one of the operands is an object (including an array), the ToPrimitive abstract operation is first called on it, which in turn is called [[DefaultValue]], with the number as the context. If it cannot be converted to a string, it is converted to a numeric type for computation.
In simple terms, string concatenation is performed if one of the operands of + is a string (or is the result of the preceding steps), and number addition is performed otherwise.
So for operators other than addition, as long as one side is a number, then the other side is converted to a number.
20. Why does it happenBigIntThe proposal?
In JavaScript, number.max_safe_INTEGER represents the maximum safe Number, which is calculated to be 9007199254740991, i.e. no precision loss (except decimals) occurs within this range. However, once beyond this range, js will appear inaccurate calculation, which has to rely on some third-party libraries to solve the problem when calculating large numbers, so the official proposed BigInt to solve this problem.
21. Object. Assign and extend operations are deep copy or shallow copy
Extension operators:
let outObj = {
inObj: {a: 1.b: 2}}letnewObj = {... outObj} newObj.inObj.a =2
console.log(outObj) // {inObj: {a: 2, b: 2}}
Copy the code
Object.assign():
let outObj = {
inObj: {a: 1.b: 2}}let newObj = Object.assign({}, outObj)
newObj.inObj.a = 2
console.log(outObj) // {inObj: {a: 2, b: 2}}
Copy the code
As you can see, both are shallow copies.
- The object.assign () method accepts the first argument as the target Object, and all subsequent arguments as the source Object. All the source objects are then merged into the target object. It modifies an object, so it fires the ES6 setter.
- The extension operator (…) When you use it, each value in an array or object is copied into a new array or object. It does not copy inherited properties or class properties, but it does copy ES6’s symbols property.
Second, the ES6
Let, const, var
(1) Block-level scope: Block scope is included by {}, let and const have block-level scope, var does not have block-level scope. Block-level scope solves two problems in ES5:
- Inner variables may override outer variables
- Loop variables used for counting are leaked as global variables
(2) Variable promotion: var exists variable promotion, let and const does not exist variable promotion, that is, the variable can only be used after the declaration, if not, an error will be reported.
(3) Add properties to the global: the global object of browser is window, and the global object of Node is global. Var declares a global variable and adds it as a property of the global object, but let and const do not.
(4) Repeat declaration: when var declares a variable, it can repeat the declaration of the variable, and the later declared variable with the same name will overwrite the previous declared traversal. Const and let do not allow repeated declarations of variables.
(5) Temporary dead zone: a variable is not available until it is declared with let or const commands. This is grammatically called a temporary dead zone. Variables declared with var do not have temporary dead zones.
(6) Initial value setting: in the variable declaration, var and let can not set the initial value. A const declaration must have an initial value.
(7) Pointers to: let and const are new syntax for creating variables in ES6. Let creates a variable that can change the pointer to (can be reassigned). However, variables declared as const are not allowed to change the point of the pointer.
The difference between | var | let | const |
---|---|---|---|
Whether there is block level scope | x | ✔ ️ | ✔ ️ |
Whether there is a variable promotion | ✔ ️ | x | x |
Whether to add global properties | ✔ ️ | x | x |
Can you declare variables repeatedly | ✔ ️ | x | x |
Whether temporary dead zones exist | x | ✔ ️ | ✔ ️ |
Whether an initial value must be set | x | x | ✔ ️ |
Can you change the pointer to | ✔ ️ | ✔ ️ | x |
2. Can properties of const objects be modified
Const guarantees not that the value of the variable cannot be changed, but that the memory address to which the variable points cannot be changed. For data of a basic type (numeric, string, Boolean), the value is stored at the memory address that the variable points to and is therefore equivalent to a constant.
But for data of reference type (mainly objects and arrays), a variable that points to the memory address of the data is only a pointer. Const guarantees that the pointer is fixed, but that the data structure it points to is not mutable.
3. What if new is the arrow function
It does not have a prototype, it does not have a “this” reference, and it does not have arguments, so it is not possible to create a New arrow function.
The implementation of the new operator is as follows:
- Create an object
- Assign the scope of the constructor to the new object (i.e. point the object’s __proto__ property to the constructor’s prototype property)
- Points to the code in the constructor, where this points to the object (that is, adds properties and methods to the object)
- Return a new object
Therefore, the second and third arrow functions above are not executed.
4. The difference between arrow function and ordinary function
(1) Arrow functions are more concise than ordinary functions
- If there are no arguments, just write an empty parenthesis
- If you have only one argument, you can leave out the parentheses
- If there are multiple arguments, separate them with commas
- If the body of a function returns only one sentence, the braces can be omitted
- If the body of the function does not require a return value and only has one sentence, precede the statement with the void keyword. The most common is to call a function:
let fn = () = > void doesNotReturn();
Copy the code
(2) The arrow function does not have its own this
The arrow function doesn’t create its own this, so it doesn’t have its own this, it just inherits this one level above its scope. So the point to this in the arrow function is fixed when it’s defined, and it doesn’t change afterwards.
(3) The this point inherited from the arrow function never changes
var id = 'GLOBAL';
var obj = {
id: 'OBJ'.a: function(){
console.log(this.id);
},
b: () = > {
console.log(this.id); }}; obj.a();// 'OBJ'
obj.b(); // 'GLOBAL'
new obj.a() // undefined
new obj.b() // Uncaught TypeError: obj.b is not a constructor
Copy the code
Object obj’s method b is defined using an arrow function. This in this function always points to this in the global execution environment in which it was defined. Even if the function is called as a method on object obj, this still points to the Window object. Note that the brace {} that defines an object does not form a separate execution environment; it is still in the global execution environment.
(4) Call (), apply(), bind() and other methods cannot change the point of this in the arrow function
var id = 'Global';
let fun1 = () = > {
console.log(this.id)
};
fun1(); // 'Global'
fun1.call({id: 'Obj'}); // 'Global'
fun1.apply({id: 'Obj'}); // 'Global'
fun1.bind({id: 'Obj'}) ();// 'Global'
Copy the code
(5) Arrow functions cannot be used as constructors
The new step of the constructor is described above, but the second step is actually to point this in the function to that object. However, since the arrow function does not have its own this, and this points to the outer execution environment and cannot be changed, it cannot be used as a constructor.
(6) The arrow function has no arguments of its own
The arrow function does not have its own Arguments object. Accessing Arguments in the arrow function actually returns the arguments value of its outer function.
(7) Arrow function has no prototype
(8) The arrow function cannot be used as a Generator function. The yeild keyword cannot be used
5. Arrow functionthisPointing to where?
Unlike traditional JavaScript functions, the arrow function does not have its own “this”. It captures the value of this in its context as its own “this” value and is not called by new because it does not have its own “this”. This so-called “this” will not change either.
To understand the arrow function, use Babel:
// ES6
const obj = {
getArrow() {
return () = > {
console.log(this=== obj); }; }}Copy the code
After the transformation:
// ES5, translated by Babel
var obj = {
getArrow: function getArrow() {
var _this = this;
return function () {
console.log(_this === obj); }; }};Copy the code
6. The functions and usage scenarios of the extended operators
(1) The object extension operator
Object extension operator (…) Use to fetch all traversable properties from a parameter object and copy them to the current object.
let bar = { a: 1.b: 2 };
letbaz = { ... bar };// { a: 1, b: 2 }
Copy the code
The above method is actually equivalent to:
let bar = { a: 1.b: 2 };
let baz = Object.assign({}, bar); // { a: 1, b: 2 }
Copy the code
The object. assign method is used to merge objects, copying all enumerable properties of the source Object to the target. The first argument to the object. assign method is the target Object, and all subsequent arguments are the source Object. If the target object has a property of the same name as the source object, or if more than one source object has a property of the same name, the later property overrides the previous one.
Similarly, if a user-defined property is placed after an extension operator, the property of the same name inside the extension operator will be overridden.
let bar = {a: 1.b: 2};
letbaz = {... bar, ... {a:2.b: 4}}; // {a: 2, b: 4}
Copy the code
Using the above features, you can easily modify some properties of an object. In redux, the reducer function must be a pure function, and the state object in the reducer cannot be modified directly. You can use the extension operator to copy all the objects in the modified path, and then generate a new object to return.
Note that the extended operator’s copy of an object instance is a shallow copy.
(2) Array extension operator
The array extension operator converts an array into a comma-separated sequence of arguments, expanding the array one level at a time.
console.log(... [1.2.3])
/ / 1 2 3
console.log(... [1[2.3.4].5])
// 1 [2, 3, 4] 5
Copy the code
Here’s how the array extension operator works:
- Converts an array to a sequence of arguments
function add(x, y) {
return x + y;
}
const numbers = [1.2]; add(... numbers)/ / 3
Copy the code
- Copy the array
const arr1 = [1.2];
const arr2 = [...arr1];
Copy the code
Remember: The extension operator (…) Copy all the traversable properties of the argument object into the current object, where the argument object is an array. All the objects in the array are of the underlying data types. Copy all the underlying data types into the new array.
- Merge array
If you want to merge an array within an array, you can do this:
const arr1 = ['two'.'three'];const arr2 = ['one'. arr1,'four'.'five'];// ["one", "two", "three", "four", "five"]
Copy the code
- The extension operator is used in combination with a destruct assignment to generate an array
const [first, ...rest] = [1.2.3.4.5]; first// 1rest // [2, 3, 4, 5]
Copy the code
Note: If you use the extension operator for array assignment, you must place it at the end of the argument, otherwise an error will be reported.
const [...rest, last] = [1.2.3.4.5]; / / error const [first, the rest of..., the last] = [1, 2, 3, 4, 5]. / / an error
Copy the code
- Turn a string into a real array
[...'hello'] // [ "h", "e", "l", "l", "o" ]
Copy the code
- Any Iterator interface object can be turned into a true array using the extension operator
A common application is the ability to convert certain data structures into arrays:
/ / the arguments object
function foo() {
const args = [...arguments];
}
Copy the code
Used to replace the es5 Array. Prototype. Slice. The call (the arguments) writing.
- use
Math
The getvalue () function gets a specific value from an array
const numbers = [9.4.7.1];
Math.min(... numbers);/ / 1
Math.max(... numbers);/ / 9
Copy the code
7. What functions can Proxy achieve?
In Vue3.0, Proxy is used to replace the original Object. DefineProperty to implement data response.
Proxy is a new feature in ES6 that allows you to define operations from objects.
let p = new Proxy(target, handler)
Copy the code
Target represents the object to which the agent is to be added, and handler is used to define operations within the object. For example, a set or get function can be used to define operations.
Let’s implement a data response using a Proxy:
let onWatch = (obj, setBind, getLogger) = > {
let handler = {
get(target, property, receiver) {
getLogger(target, property)
return Reflect.get(target, property, receiver)
},
set(target, property, value, receiver) {
setBind(value, property)
return Reflect.set(target, property, value)
}
}
return new Proxy(obj, handler)
}
let obj = { a: 1 }
let p = onWatch(
obj,
(v, property) = > {
console.log('Listen to attribute${property}Change for${v}`)},(target, property) = > {
console.log(` '${property}'=${target[property]}`)
}
)
p.a = 2 // Listen for attribute a change
p.a // 'a' = 2
Copy the code
In the above code, we insert our function logic into the original logic by custom set and get functions to notify when any property of an object is read or written.
Of course, this is a simple version of the reactive implementation. If you need to implement a reactive in Vue, you need to collect dependencies in GET and distribute updates in SET. The reason why Vue3.0 uses Proxy instead of the original API is that Proxy does not need to recursively add proxies for each property. The above operations can be completed in one time, and the performance is better. In addition, some data updates cannot be monitored in the original implementation, but the Proxy can perfectly monitor any data changes. The only drawback is poor compatibility of the browser.
8. Understanding the deconstruction of objects and arrays
Deconstruction is a new mode of data extraction provided by ES6. This mode can get the desired value from the object or array specifically. When the array is destructed, the desired data is extracted based on the position of the element as the matching condition:
const [a, b, c] = [1.2.3]
Copy the code
Finally, a, b, and C are given the 0, 1, and 2 index bits of the array, respectively:The 0, 1, and 2 element values in the array are mapped to the 0, 1, and 2 variables on the left. This is how array deconstructing works. You can also set empty space for the left variable array to achieve accurate extraction of several elements in the array:
const [a,,c] = [1.2.3]
Copy the code
By leaving the middle bit blank, we can assign the first and last digit of the array to the a and C variables:
Object deconstruction is a little more complicated and powerful than array structuring. When an object is deconstructed, the desired data is extracted with the name of the attribute as the matching condition. Now define an object:
const stu = {
name: 'Bob'.age: 24
}
Copy the code
If you want to deconstruct its two properties, you can do this:
const { name, age } = stu
Copy the code
This gives you two variables, name and age, which are equal to stu:
Note that object deconstruction is strictly based on the property name, so swapping the name and age will give the same result:
const { age, name } = stu
Copy the code
9. How to extract a specified attribute in a highly nested object?
Sometimes you will encounter objects that are very deeply nested:
const school = {
classes: {
stu: {
name: 'Bob'.age: 24,}}}Copy the code
The name variable, like here, is nested at four levels. If you still try to extract it in the old way:
const { name } = school
Copy the code
Obviously, this does not work, because the school object itself does not have a name property, the name is in the school object “son of son” object. A silly way to extract the name is to deconstruct it layer by layer:
const { classes } = school
const { stu } = classes
const { name } = stu
name // 'Bob'
Copy the code
But there is a more standard way to solve this problem with a single line of code:
const { classes: { stu: { name } }} = school
console.log(name) // 'Bob'
Copy the code
You can further deconstruct the variable name by colon +{target attribute name} to the right of the decomposed variable name until you get the target data.
10. Understanding rest parameters
When an extension operator is used on a function parameter, it can also combine a separate sequence of arguments into an array:
function mutiple(. args) {
let result = 1;
for (var val of args) {
result *= val;
}
return result;
}
mutiple(1.2.3.4) / / 24
Copy the code
Here, mutiple is passed four separate arguments, but if we try to print args in the mutiple function, we’ll see that it’s an array:
function mutiple(. args) {
console.log(args)
}
mutiple(1.2.3.4) // [1, 2, 3, 4]
Copy the code
This is… The REST operator adds another layer of power to the ability to converge multiple parameters of a function into an array. This is often used to get redundant arguments to a function, or when the number of arguments to a function is uncertain, as above.
Template syntax and string processing in ES6
ES6 introduces the concept of “template syntax”. Before ES6, concatenating strings was cumbersome:
var name = 'css'
var career = 'coder'
var hobby = ['coding'.'writing']
var finalString = 'my name is ' + name + ', I work as a ' + career + ', I love ' + hobby[0] + ' and ' + hobby[1]
Copy the code
Just a few variables, so many plus signs, and you have to be careful with the blanks and the punctuation. But with template strings, the concatenation difficulty goes straight down:
var name = 'css'
var career = 'coder'
var hobby = ['coding'.'writing']
var finalString = `my name is ${name}, I work as a ${career} I love ${hobby[0]} and ${hobby[1]}`
Copy the code
Strings are not only easier to spell, they are also easier to read, and the overall quality of the code is higher. This is the first advantage of template strings — allowing variables to be embedded in the ${} way. But that’s not the point. The key advantages of template strings are two:
- In the template string, whitespace, indentation, and newlines are preserved
- The template string fully supports “operation” expressions, which can be performed in ${}
Based on the first point, you can write HTML code directly in the template string without any obstacles:
let list = '
- Item 1
- Item 2
';
console.log(message); // The output is correct, no error is reported
Copy the code
Based on the second point, you can throw some simple calculations and calls into ${} to do this:
function add(a, b) {
const finalString = `${a} + ${b} = ${a+b}`
console.log(finalString)
}
add(1.2) // output '1 + 2 = 3'
Copy the code
In addition to template syntax, ES6 also adds a series of string methods to improve development efficiency:
(1) Existence determination: In the past, when determining whether a character/string is in a string, indexOf > -1 can only be used to do so. Now ES6 provides three methods: includes, startsWith, and endsWith, all of which return a Boolean value to tell you whether or not they exist.
- Includes: Determines the inclusion relationship between strings and substrings:
const son = 'haha'
const father = 'xixi haha hehe'
father.includes(son) // true
Copy the code
- StartsWith: determines if the string startsWith a/string:
const father = 'xixi haha hehe'
father.startsWith('haha') // false
father.startsWith('xixi') // true
Copy the code
- EndsWith: determines whether a string endsWith a character/string:
const father = 'xixi haha hehe'
father.endsWith('hehe') // true
Copy the code
(2) Automatic repetition: you can use the repeat method to make the same string output multiple times (to be copied multiple times) :
const sourceCode = 'repeat for 3 times; '
const repeated = sourceCode.repeat(3)
console.log(repeated) // repeat for 3 times; repeat for 3 times; repeat for 3 times;
Copy the code
Third, JavaScript foundation
1. Implementation principle of the new operator
Execution of the new operator:
(1) First create a new empty object
(2) Set the prototype. Set the object’s prototype to the function’s prototype object.
(3) Let this refer to this object and execute the constructor code (add properties to the new object).
(4) Determine the return value type of the function. If it is a value type, return the created object. If it is a reference type, an object of that reference type is returned.
Concrete implementation:
function objectFactory() {
let newObject = null;
let constructor = Array.prototype.shift.call(arguments);
let result = null;
// Check whether the parameter is a function
if (typeof constructor! = ="function") {
console.error("type error");
return;
}
// Create an empty object with the constructor's prototype object
newObject = Object.create(constructor.prototype);
// Point this to the new object and execute the function
result = constructor.apply(newObject, arguments);
// Determine the return object
let flag = result && (typeof result === "object" || typeof result === "function");
// Judge the return result
return flag ? result : newObject;
}
// UsageObjectFactory (constructor, initialization parameter);Copy the code
2. The difference between map and Object
Map | Object | |
---|---|---|
The accident of key | By default, the Map does not contain any keys, only explicitly inserted keys. | Object has a prototype, and the key names on the prototype chain may conflict with the key names you set on the Object. |
The type of the key | The key of a Map can be any value, including a function, an object, or any basic type. | The key of Object must be String or Symbol. |
The order of the keys | Keys in a Map are ordered. Therefore, when iterating, the Map object returns the keys in the order they were inserted. | The key of Object is unordered |
Size | The number of key-value pairs for a Map can be easily obtained by the size attribute | The number of Object key-value pairs can only be calculated manually |
The iteration | The Map is iterable, so it can be iterated directly. | An iterating Object needs to get its key in some way before it can iterate. |
performance | It performs better in scenarios where key-value pairs are frequently added and deleted. | Not optimized for scenarios where key-value pairs are frequently added and deleted. |
3. Differences between Map and weakMap
(1) Map A Map is essentially a collection of key-value pairs, but the keys in a normal Object key-value pair can only be strings. The Map data structure provided by ES6 is similar to an object, but its key is not limited in scope and can be of any type. It is a more complete Hash structure. If the key of a Map is a primitive data type, the two keys are considered the same as long as they are strictly the same.
In fact, Map is an array, and each of its data is also an array.
const map = [
["name"."Zhang"],
["age".18]]Copy the code
The following operations can be performed on Map data structures:
- size:
map.size
Returns the total number of members of the Map structure. - Set (key,value) : sets the key value corresponding to the key name, and then returns the entire Map structure. If the key already has a value, the key value will be updated, otherwise the new key will be generated. (Since the return is the current Map object, the call can be chained.)
- Get (key) : This method reads the corresponding key and returns undefined if the key is not found.
- Has (key) : This method returns a Boolean value indicating whether a key is in the current Map object.
- Delete (key) : This method removes a key, returning true, or false if the deletion fails.
- Clear () : map.clear() clears all members without returning a value.
The Map structure is provided natively with three iterator generators and one iterator method
- Keys () : the iterator that returns the key name.
- Values () : the iterator that returns the key value.
- Entries () : returns a traverser for all members.
- ForEach () : traverses all members of the Map.
const map = new Map([["foo".1],
["bar".2]])for(let key of map.keys()){
console.log(key); // foo bar
}
for(let value of map.values()){
console.log(value); / / 1. 2
}
for(let items of map.entries()){
console.log(items); // ["foo",1] ["bar",2]
}
map.forEach( (value,key,map) = > {
console.log(key,value); // foo 1 bar 2
})
Copy the code
A WeakMap object is also a set of key-value pairs, where the keys are weakly referenced. The key must be an object, the raw data type cannot be used as the key value, and the value can be arbitrary.
The object also has the following methods:
- Set (key,value) : sets the key value corresponding to the key name, and then returns the entire Map structure. If the key already has a value, the key value will be updated, otherwise the new key will be generated. (Since the return is the current Map object, the call can be chained.)
- Get (key) : This method reads the corresponding key and returns undefined if the key is not found.
- Has (key) : This method returns a Boolean value indicating whether a key is in the current Map object.
- Delete (key) : This method removes a key, returning true, or false if the deletion fails.
Its clear() method has been deprecated, so you can do it by creating an empty WeakMap and replacing the original object.
WeakMap is designed so that sometimes you want to store some data on an object, but it forms a reference to that object. Once both objects are no longer needed, the reference must be manually removed or the garbage collection mechanism will not free the memory occupied by the objects.
The objects referenced by the key name of a WeakMap are weak references, that is, the garbage collection mechanism does not take the reference into account. Thus, as long as all other references to the referenced object are cleared, the garbage collection mechanism frees the memory occupied by that object. In other words, once no longer needed, the key name object and the corresponding key value pair in the WeakMap will disappear automatically, without manually deleting the reference.
Conclusion:
- Map Data structure. It is similar to an object in that it is also a collection of key-value pairs, but the range of “keys” is not limited to strings, and all types of values (including objects) can be used as keys.
- Similar to the Map structure, the WeakMap structure is also used to generate a collection of key and value pairs. However, WeakMap only accepts objects as key names (except null) and does not accept other types of values as key names. Moreover, the object pointed to by the key name of a WeakMap is not included in the garbage collection mechanism.
4. What built-in objects JavaScript has
Global Objects, or standard built-in objects, are not to be confused with global Objects. By global objects, WE mean objects in the global scope. Other objects in the global scope can be created by a user’s script or provided by a host program.
Classification of standard built-in objects:
(1) Value properties. These global properties return a simple value that has no properties or methods of its own. Examples are the Infinity, NaN, undefined, and null literals
(2) Function attributes. Global functions can be called directly without specifying the owning object. After execution, the result will be returned to the caller directly. Examples include eval(), parseFloat(), parseInt(), and so on
(3) Basic objects, basic objects are the basis for defining or using other objects. Basic objects include generic objects, function objects, and error objects. For example, Object, Function, Boolean, Symbol, Error, etc
(4) Number and date objects, used to represent numbers, dates and objects that perform mathematical calculations. For example, Number, Math, Date
(5) String, an object used to represent and manipulate strings. For example, String and RegExp
(6) Indexable collection objects that represent collections of data sorted by index values, including arrays and arrays of types, as well as array-like objects. Such as Array
(7) Collection objects with keys that use keys when storing data, allowing for iterating elements in insertion order. For example, Map, Set, WeakMap, and WeakSet
(8) Vector set. The data in SIMD vector set will be organized into a data sequence. Such as SIMD etc.
(9) Structured data. These objects are used to represent and manipulate structured buffer data or JSON encoded data. Such as JSON,
(10) Control abstract objects such as Promise, Generator, etc
(11) Reflection. For example Reflect, Proxy
(12) Internationalization, the addition of ECMAScript objects to support multilingual processing. For example, Intl and intl. Collator
WebAssembly (13)
(14) Others. For example the arguments
Summary: Built-in objects in JS mainly refer to some global value properties, functions and constructors defined by JS that exist in global scope before program execution. Common examples are global variable values such as NaN and undefined, global functions such as parseInt() and parseFloat(), constructors that instantiate objects such as Date and Object, and built-in objects that provide mathematical computations such as the Math Object.
5. What are the common regular expressions?
// (1) Match the hexadecimal color value
var regex = /#([0-9a-fA-F]{6}|[0-9a-fA-F]{3})/g;
// (2) Match the date, for example, yyyY-MM-dd
var regex = / ^ [0-9] {4} - (0 [1-9] | [0-2] 1) - (0 | [1-9] [12] [0-9] [01]) | 3 $/;
// (3) match qq number
var regex = / ^ (1-9] [0-9] {4, 10} $/ g;
// (4) Mobile phone number regular
var regex = /^1[34578]\d{9}$/g;
// (5) The user name is regular
var regex = / ^ [a zA - Z \ $] [a zA - Z0 - _ \ $9] $/ dec {4};
Copy the code
6. Understanding JSON
JSON is a lightweight text-based data exchange format. It can be read in any programming language and passed as a data format.
In project development, JSON is used as a way of data exchange in front and back end. In the front end, a data structure in accordance with JSON format is serialized into JSON string, and then it is passed to the back end. The back end generates the corresponding data structure after parsing the string in JSON format, so as to realize the transmission of data in front and back ends.
Since JSON’s syntax is js based, it’s easy to confuse objects in JSON with objects in JS. However, it’s important to note that JSON is not the same as objects in JS. Objects in JSON are more strictly formatted. There is no NaN, so most JS objects are not in the same format as JSON objects.
In the JS provides two functions to achieve js data structure and JSON format conversion processing,
- The json. stringify function converts a jSON-formatted data structure to a JSON string by passing it in. If the incoming data structure does not conform to the JSON format, special processing is performed on the values during serialization to make them conform to the specification. When the front end sends data to the back end, you can call this function to convert the data object into a string in JSON format.
- The json.parse () function, which converts a jSON-formatted string to a JS data structure, will throw an error if the string passed is not a standard JSON-formatted string. When you receive a string in JSON format from the back end, you can parse it into a JS data structure using this method to access the data.
7. What are the ways of lazy loading JavaScript scripts?
Lazy loading is waiting for the page to load before loading the JavaScript file. Js lazy loading helps speed up page loading.
There are generally the following ways:
- The defer property: Add the defer property to the JS script, which will cause the loading of the script to be parsed in sync with the parsing of the document, and then execute the script file after the document is parsed, so that the rendering of the page is not blocked. Multiple scripts that set the defer property are executed last in order by specification, but this may not be the case in some browsers.
- Async property: add async property to the JS script. This property will make the script load asynchronously and will not block the page parsing process. However, the js script will be executed immediately after the script is loaded. Scripts with multiple async properties have unpredictable execution orders and generally do not execute in the order of the code.
- Dynamic CREATION of THE DOM: dynamic creation of the DOM tag, the document can be loaded to listen to the event, when the document is loaded to create a script tag to introduce the JS script.
- Use the setTimeout delay method: set a timer to load the JS script file lazily
- Make JS load last: Place the JS script at the bottom of the document so that the JS script is loaded and executed as late as possible.
8. How to define an array object in JavaScript?
An object that has a length property and several index properties is called an array-like object. An array-like object is like an array, but cannot call the methods of an array. Common array-like objects are the returns of arguments and DOM methods. A function can also be considered an array-like object because it contains the value of the length attribute, which represents the number of arguments that can be accepted.
There are several common array-like conversion methods:
(1) The conversion is implemented by calling the slice method of the array
Array.prototype.slice.call(arrayLike);
Copy the code
(2) The conversion is realized by calling the splice method of the array by call
Array.prototype.splice.call(arrayLike, 0);
Copy the code
(3) Use apply to call the concat method of the array to achieve the transformation
Array.prototype.concat.apply([], arrayLike);
Copy the code
(4) Use the array. from method to implement the conversion
Array.from(arrayLike);
Copy the code
9. What are the native methods of arrays?
- Array and string conversion methods: toString(), toLocalString(), join() where the join() method can specify the delimiter for conversion toString.
- There are pop() and push() methods that operate on the end of an array. The push method can pass multiple arguments.
- Reverse () and sort(). Sort () can be passed a function to compare the two values, and if the return value is positive, the positions of the two arguments are swapped.
- The concatenated array method concat() returns the concatenated array without affecting the original array.
- The array slice() method is used to slice a part of an array and return it without affecting the original array.
- The array insertion method splice(), the method that affects the original array to find the indexOf a particular item, the indexOf() and lastIndexOf() iterative methods every(), some(), filter(), map(), and forEach() methods
- Array merging methods reduce() and reduceRight()
10. What are the differences between Unicode, UTF-8, UTF-16, and UTF-32?
(1) Unicode
Before we talk about Unicode, we need to know about ASCII codes: The American Standard Code for Information Interchange is called the American Standard Information Interchange Code.
- It is a computer coding system based on the Latin alphabet.
- It defines a dictionary for representing common characters.
- It contains “a-z “(with case), data “0-9”, and some common symbols.
- Designed specifically for English, it has 128 encodings that do little for other languages
ASCII code can be represented by a limited number of encodings. To represent the encodings of other languages, Unicode is still used, which can be said to be the superset of ASCII.
Unicode full name Unicode Translation Format, also known as Unicode, universal code, single code. Unicode is produced to solve the limitations of traditional character encoding schemes. It sets a uniform and unique binary encoding for each character in each language, so as to meet the requirements of cross-language and cross-platform text conversion and processing.
There are many implementations (that is, encodings) of Unicode, the common ones being UTF-8, UTF-16, UTF-32, and USC-2.
(2) the utf-8
Utf-8 is the most widely used Unicode encoding. Utf-8 is a variable-length encoding that can range from 1 to 4 bytes and is fully compatible with 128 ASCII characters.
Note: UTF-8 is an encoding; Unicode is a set of characters.
Utf-8 encoding rules:
- forsingle-byteThe first byte is 0 and the next 7 bits are of this character
Unicode
Code, so for English letters, itsUnicode
Coding andACSII
The code is the same. - forN bytesThe first n bits of the first byte are all 1, the NTH +1 bit is set to 0, and the first two bits of the following bytes are all set to 10. The rest of the unmentioned binary bits are all of this symbol
Unicode
Code.
Take a look at the specific Unicode numbering range and the corresponding UTF-8 binary format:
Coding range (decimal number corresponding to the number) | Binary format |
---|---|
0 x00-0 x7f (0-127) | 0xxxxxxx |
0 x80-0 x7ff (128-2047), | 110xxxxx 10xxxxxx |
0 x800-0 XFFFF (2048-65535), | 1110xxxx 10xxxxxx 10xxxxxx |
0x10000 — 0x10FFFF (above 65536) | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx |
So how do you do the utF-8 encoding with the Unicode encoding? The steps are as follows:
- To find the
Unicode
To find the corresponding binary format - will
Unicode
Code conversion to binary number (remove the highest 0 bit) - Filling binary numbers from right to left in binary format at one time
X
If there isX
If you don’t fill it in, set it to 0
A practical example: The Unicode encoding for the word “horse” is: 0x9A6C, the integer number is 39532 (1) Preferred to determine the character in the third range, it is in the format 1110XXXX 10xxXXXX 10xxXXXX (2) 39532 corresponds to the binary number 1001 1010 0110 1100 (3) Fill the binary number into X, The result: 11101001 10101001 10101100
(3) the UTF – 16
1. The concept of planes
Before you get into UTF-16, let’s look at the concept of planes: The Unicode encoding has many, many characters that are not defined at once, but are defined in partitions, 65536 (216) characters per partition, which is called a plane. There are currently 17 planes.
The first plane is called the basic plane with code points ranging from 0 — 216-1, which is written in hexadecimal as U+0000 — U+FFFF. The remaining 16 planes are called the auxiliary plane with code points ranging from U+10000 — U+10FFFF.
2. Utf-16 concept
Utf-16 is also an encoding form of the Unicode code set. It maps abstract code points of the Unicode character set to a sequence of 16-bit long integers, or symbols, for data storage or transmission. Unicode character code points require one or two 16-bit long symbols to represent, so UTF-16 is also represented in variable-length bytes.
3. Utf-16 encoding rules:
- Serial number in
U + 0000 - U + FFFF
The character (common character set) of, represented directly by two bytes. - Serial number in
U + 10000 - U + 10 FFFF
Between characters, which need to be represented by four bytes.
4. Code recognition
So the question is, when you have two bytes, how do you know whether to treat it as a character or to treat it as a character with the next two bytes?
Utf-16 encoding certainly takes this into account. In the basic plane, the range from U+D800 to U+DFFF is a null segment, that is, the code points in this range do not correspond to any characters, so these empty segments can be used to map the characters in the auxiliary plane.
The auxiliary plane has a total of 220 character bits, so representing these characters requires at least 20 binary bits. Utf-16 splits these 20 bits in half, with the first 10 bits mapped to U+D800 — U+DBFF, called the high bit (H), and the last 10 bits mapped to U+DC00 — U+DFFF, called the low bit (L). This is equivalent to splitting the characters of one auxiliary plane into the characters of two basic planes.
Therefore, when you encounter two bytes that have a code point between U+D800 — U+DBFF, you know that the next two bytes should have a code point between U+DC00 — U+DFFF. These four bytes must be read together.
5. Give an example
For example, the word “𡠀” has a Unicode code point 0x21800, which is outside the base plane and therefore needs to be represented in four bytes. The steps are as follows:
- First calculate the result of the excess:
0x21800 - 0x10000
- Convert the above calculation result into a binary number of 20 bits. If the number is less than 20 bits, add 0 in front of it. The result is:
0001000110, 0000000000,
- The two resulting 10-bit binary numbers correspond to each interval
U+D800
The corresponding binary number is1101100000000000
That will be0001000110
Fill in its last 10 bits and get1101100001000110
Is converted to a hexadecimal number0xD846
. Similarly, the low position is zero0xDC00
“, so the wordUTF-16
Encoded as0xD846 0xDC00
(4) UTF – 32
Utf-32 is a binary integer for the number of characters. Each character is four bytes. This is converted directly. This coding method takes up more storage space, so it is used less.
For example, the Unicode number of “horse” is U+9A6C, and the integer number is 39532, which is directly converted to binary: 1001 1010 0110 1100, which is its UTF-32 encoding.
(5) Summary
What is the difference between Unicode, UTF-8, UTF-16, and UTF-32?
Unicode
Is the coded character set (CHARset), andUTF-8
,UTF-16
,UTF-32
Is the character set encoding (encoding rule);UTF-16
Encoding using a sequence of variable-length symbols as opposed to a sequence of fixed-length symbolsUTF-32
The algorithm is more complex, even more complex, than that of the same variable-length sequence of symbolsUTF-8
It’s more complex because it introduces a uniqueThe agent ofSuch a proxy mechanism;UTF-8
The starting flag information in each byte needs to be determined, so if a byte is incorrectly transmitted, the following bytes will also be parsed incorrectly. whileUTF-16
Will not judge the beginning of the logo, even if the error will be wrong only one character, so the fault tolerance ability to teach strong;- If the character content is entirely English or mixed with other text, but English is mostly English, then use
UTF-8
thanUTF-16
It saves a lot of space; If the characters are all Chinese like characters or mixed characters are mostly Chinese, thenUTF-16
You have an advantage, you can save a lot of space;
11. What are the common bitwise operators? What is the calculation rule?
Data in modern computers are stored in binary form, that is, in two states of 0 and 1. The operations performed by computers on binary data, such as addition, subtraction, multiplication and division, are called bit operations, that is, the operation involving sign bits together.
There are several common bit operations:
The operator | describe | algorithm |
---|---|---|
& |
with | If both bits are 1, the result is 1 |
` | ` | or |
^ |
Exclusive or | If two bits are the same, they are 0. If they are different, they are 1 |
~ |
The not | 0 goes to 1,1 goes to 0 |
<< |
Shift to the left | Each binary bit is shifted to the left by a number of bits, the high bit is discarded, and the low bit is supplemented by 0 |
>> |
Moves to the right | Each binary bit all right shift a number of bits, positive left complement 0, negative left complement 1, the right discard |
1. Bitwise and operator (&)
Definition: The two data to participate in the operation are “and” operation according to binary bits. Operation rules:
0 & 0 = 0
0 & 1 = 0
1 & 0 = 0
1 & 1 = 1
Copy the code
Conclusion: If both digits are 1, the result is 1; otherwise, the result is 0. For example, 3&5 is:
0000 0011
0000 0101
= 0000 0001
Copy the code
So 3&5 has a value of 1. Note: Negative numbers take part in bitwise and operation in complement form.
USES:
(1) Determine parity
It just depends on whether the least digit is 0 or 1, 0 is even, 1 is odd. If ((I & 1) == 0) if (I % 2 == 0)
(2) Clear zero
If you want to zero out a cell, even if all its bits are zero, if you match it with a value whose bits are all zero, the result will be zero.
2. The bitwise or operator (|)
Definition: Two objects that participate in the operation “or” operation according to binary bits.
Operation rules:
0 | 0 = 0
0 | 1 = 1
1 | 0 = 1
1 | 1 = 1
Copy the code
Conclusion: As long as one of the two objects participating in the operation is 1, its value is 1. For example: 3 | 5:
0000 0011
0000 0101
= 0000 0111
Copy the code
Therefore, 3 | 5 has a value of 7. Note: Negative numbers take part in bitwise or operations in complement form.
3. Xor operator (^)
Definition: The two data involved in the operation perform xOR operation according to binary bits.
Operation rules:
0 ^ 0 = 0
0 ^ 1 = 1
1 ^ 0 = 1
1 ^ 1 = 0
Copy the code
Summary: two objects that participate in the operation, if the two corresponding bits are the same, are 0, and if they are different, they are 1. For example: 3 | 5:
0000 0011
0000 0101
= 0000 0110
Copy the code
So the value of 3 to the fifth is 6. Properties of the XOR operation:
- Commutative law:
(a^b)^c == a^(b^c)
- Associative law:
(a + b)^c == a^b + b^c
- For any number x, it’s going to be
X ^ x = 0, x ^ 0 = x
- Reflexive:
a^b^b=a^0=a
;
4. Take the inverse operator (~)
Definition: A data that participates in an operation is “inverted” by binary.
Operation rules:
~ 1 = 0~ 0 = 1
Copy the code
Summary: to a binary number bitwise inverse, is 0 to 1,1 to 0. For example, ~6 is:
0000 0110= 1111 1001
Copy the code
In a computer, positive numbers are represented by the original code, and negative numbers are stored by the complement code. First look at the highest bit. The highest bit, 1, represents a negative number and 0, represents a positive number. The computer binary code is negative and the highest bit is the sign bit. When we find that the bitwise is negative, we directly take its complement and change it to decimal:
0000 0110 = 1111 1001Radix-minus-one complement:1000 0110Complement:1000 0111
Copy the code
Therefore, the value of ~6 is -7.
5. Left-shift operator (<<)
Definition: the binary bits of an operation are shifted to the left by a number of bits, the left bits are discarded, and the right bits are filled with 0. Let a=1010 1110, a= a<< 2, move the binary bit of A to the left by 2 bits and add 0 to the right, so that a=1011 1000. If the high number discarded by the left shift does not contain 1, then each left shift is equivalent to multiplying that number by 2.
6. Right shift operator (>>)
Definition: the binary bits of a number are shifted to the right by a number of bits. The left complement of positive numbers is 0, the left complement of negative numbers is 1, and the right side is discarded. For example: a=a>>2 Moves the binary bit of A to the right by 2 bits. The left complement of 0 or 1 depends on whether the number shifted is positive or negative. Every one to the right of an operand is the same thing as dividing it by 2.
7. The original code, complement code, inverse code
The above mentioned complement code, inverse code and other knowledge, here is a supplement. There are three ways to express signed numbers in computer, namely, source code, inverse code and complement code. The three methods all have two parts: sign bit and numeric bit. The sign bit is 0 for “positive” and 1 for “negative”, while the numeric bit is different in the three methods.
(1) Source code
The source code is just a binary number of a number. For example, the source code of 10 is 0000 1010
(2) inverse code
- The inverse code of positive numbers is the same as the original code, such as: 10 inverse code is 0000 1010
- The inverse code of a negative number is the division sign bit.
For example: – 10
The original code:1000 1010Radix-minus-one complement:1111 0101
Copy the code
(3) Complement
- The complement of positive numbers is the same as the original code, such as: 10 complement is 0000 1010
- The negative number’s complement is the inverse of all the bits of the original code except for the sign bits so 0 goes to 1, 1 goes to 0, and then you add 1, so the inverse code goes to 1.
For example: – 10
The original code:1000 1010Radix-minus-one complement:1111 0101Complement:1111 0110
Copy the code
12. Why is the arguments for a function an array of classes instead of an array? How do I iterate over an array of classes?
Arguments is an object whose properties are an ascending number starting from 0, as well as callee and length attributes, similar to arrays; However, they do not have the usual method properties of arrays, such as forEach, reduce, etc., so they are called class arrays.
To traverse an array of classes, there are three methods:
(1) To apply an array method to a class array, you can use the call and apply methods.
function foo(){
Array.prototype.forEach.call(arguments.a= > console.log(a))
}
Copy the code
(2) Convert a class Array to an Array using the array. from method:
function foo(){
const arrArgs = Array.from(arguments)
arrArgs.forEach(a= > console.log(a))
}
Copy the code
(3) Use the expansion operator to convert the class array into an array
function foo(){
const arrArgs = [...arguments]
arrArgs.forEach(a= > console.log(a))
}
Copy the code
13. What are DOM and BOM?
- DOM refers to the Document Object model, which refers to the document as an object that primarily defines methods and interfaces for handling web content.
- BOM refers to the Browser Object model. It refers to treating the browser as an object that defines the methods and interfaces to interact with the browser. The core of the BOM is the window, and the Window object has the dual role of being both an interface to the browser window through JS and a Global object. This means that any object, variable, or function defined in a web page exists as a property or method of the global object. The window object contains sub-objects such as location object, Navigator object, Screen object and so on. The document object, the most fundamental object of DOM, is also a sub-object of the BOM Window object.
14. How to convert an array-like object into an array
An object that has a length property and several index properties is called an array-like object. An array-like object is like an array, but cannot call the methods of an array. A common array-like object is the return of arguments and DOM methods. A function argument can also be thought of as an array-like object because it contains the value of the length attribute, which represents the number of arguments that can be accepted.
There are several common array-like conversion methods:
- The conversion is done by calling the array’s slice method
Array.prototype.slice.call(arrayLike);
Copy the code
- The transformation is done by calling the splice method of the array by call
Array.prototype.splice.call(arrayLike, 0);
Copy the code
- The transformation is implemented by calling the concat method on the array using Apply
Array.prototype.concat.apply([], arrayLike);
Copy the code
- The conversion is done through the array. from method
Array.from(arrayLike);
Copy the code
15. The difference between escape, encodeURI, and encodeURIComponent
- EncodeURI escapes the entire URI, converting illegal characters in the URI to valid characters. Therefore, some characters that have special meaning in the URI are not escaped.
- EncodeURIComponent is an escape of the components of the URI, so some special characters are escaped as well.
- Escape and encodeURI have the same effect, but they are different for characters other than unicode encoding 0xff. Escape simply prepended %u to the Unicode encoding of the character. The encodeURI first converts the character to UTF-8 and prefixes each byte with %.
16. Understand AJAX and implement an AJAX request
AJAX is the abbreviation for Asynchronous JavaScript and XML. It refers to the Asynchronous communication of JavaScript to get the DATA from the XML document from the server, and then update the corresponding part of the current web page without refreshing the entire web page.
Steps to create an AJAX request:
- Create an XMLHttpRequest object.
- An HTTP request is created on this object using the open method. The parameters required by the open method are the method of the request, the address of the request, whether it is asynchronous, and the authentication information of the user.
- Before making the request, you can add some information and listening functions to the object. For example, you can add header information to the request through the setRequestHeader method. You can also add a state listener to this object. An XMLHttpRequest object has five states. When its state changes, the onReadyStatechange event is triggered. You can set the listener function to handle the result of a successful request. When the readyState of the object changes to 4, it indicates that the data returned by the server has been received. At this time, we can judge the state of the request. If the state is 2xx or 304, it indicates that the request is returned to normal. At this point, the page can be updated using the data in response.
- When the properties and listening functions of the object are set, the sent method is finally called to make a request to the server, passing in parameters as the body of data to be sent.
const SERVER_URL = "/server";
let xhr = new XMLHttpRequest();
// Create the Http request
xhr.open("GET", url, true);
// Set the status listener function
xhr.onreadystatechange = function() {
if (this.readyState ! = =4) return;
// When the request succeeds
if (this.status === 200) {
handle(this.response);
} else {
console.error(this.statusText); }};// Set the listener function when the request fails
xhr.onerror = function() {
console.error(this.statusText);
};
// Set the request header
xhr.responseType = "json";
xhr.setRequestHeader("Accept"."application/json");
// Send an Http request
xhr.send(null);
Copy the code
Encapsulate AJAX with promises:
// Promise package implementation:
function getJSON(url) {
// Create a Promise object
let promise = new Promise(function(resolve, reject) {
let xhr = new XMLHttpRequest();
// Create a new HTTP request
xhr.open("GET", url, true);
// Set the listening function for the state
xhr.onreadystatechange = function() {
if (this.readyState ! = =4) return;
// Change the state of the promise when the request succeeds or fails
if (this.status === 200) {
resolve(this.response);
} else {
reject(new Error(this.statusText)); }};// Set the error listener function
xhr.onerror = function() {
reject(new Error(this.statusText));
};
// Set the data type of the response
xhr.responseType = "json";
// Set the request header
xhr.setRequestHeader("Accept"."application/json");
// Send an HTTP request
xhr.send(null);
});
return promise;
}
Copy the code
17. Why does JavaScript use variable promotion and what problems does it cause?
The effect of variable promotion is that variables declared anywhere in the function seem to be promoted to the top of the function and can be accessed before the variable is declared without error.
The essential reason for the improvement of variable declaration is that the JS engine has a process of parsing before the code execution, creating the execution context and initializing some objects that need to be used when the code is executed. When access to a variable to the current execution context to look up the scope chain, and the first end of the scope chain point to is the variable object of the current execution context, the variable object is an attribute of the execution context, which contains the function parameter, all function and variable declarations, the object is created when the code parsing.
First of all, when JS gets a variable or a function, there will be two steps, namely parsing and execution.
- In the parsing phase, JS checks the syntax and precompiles the function. When parsing, it will first create a global execution context. It will first take out variables and function declarations that will be executed in the code, and assign variables to undefined, and declare functions to be used first. Before a function is executed, a function execution context is also created, similar to the global execution context, except that the function execution context includes this, arguments, and function arguments.
- Global context: variable definition, function declaration
- Function context: variable definition, function declaration, this, arguments
- In the execution phase, the code is executed sequentially.
So why do we do variable enhancement? There are two main reasons:
- To improve performance
- Fault tolerance is better
(1) Improve performance Before JS code is executed, syntax checking and precompiling are performed only once. This is done to improve performance. Without this step, the variable (function) would have to be parsed again each time the code is executed. This is not necessary because the code for the variable (function) does not change.
During parsing, precompiled code is also generated for the function. During precompilation, it counts which variables are declared, which functions are created, and compresses the code of the functions to remove comments, unnecessary white space, and so on. The benefits of doing this are that each time a function is executed, the stack space is allocated directly to the function (no need to parse it again to find out which variables are declared and which functions are created), and the code executes faster because of code compression.
(2) Better fault tolerance
To improve the fault tolerance of JS to a certain extent, look at the following code:
a = 1;var a;console.log(a);
Copy the code
If there was no variable promotion, these two lines of code would have reported an error, but because of the variable promotion, the code would have executed normally.
While this can be completely avoided during the development process, sometimes the code is complex. It may have been used before definition because of negligence, so it will not affect normal use. Due to the presence of variable promotion, it will work properly.
Conclusion:
- Declaration enhancements during parsing and precompilation can improve performance by allowing functions to preallocate stack space for variables at execution time
- Declaration promotion can also improve the fault tolerance of JS code, so that some non-standard code can also be normal execution
Although variable promotion has some advantages, it can also cause some problems. ES6 introduced let and const to define variables, they do not have the mechanism of variable promotion. Here’s a look at some of the problems that can result from variable lifting:
var tmp = new Date(a);function fn(){
console.log(tmp);
if(false) {var tmp = 'hello world';
}
}
fn(); // undefined
Copy the code
In this function, we are supposed to print out the outer TMP variable, but because of the variable upgrade problem, the inner TMP is referred to the top of the function, which is equivalent to overwriting the outer TMP, so the print result is undefined.
var tmp = 'hello world';
for (var i = 0; i < tmp.length; i++) {
console.log(tmp[i]);
}
console.log(i); / / 11
Copy the code
Since I defined in the traversal will be promoted to a global variable that will not be destroyed after the function ends, print out 11.
18. What is a tail call and what are the benefits of using it?
A tail call is when the last step of a function calls another function. Code execution is stack based, so when a function is called inside another function, the current execution context is retained, and a new execution context is added to the stack. With tail-call optimization, you can save memory by not having to keep the current execution context because it is the last step of the function. This is called tail-call optimization. However, in ES6, tail-call optimization is only enabled in strict mode; normal mode is invalid.
19. ES6Module andCommonJSWhat are the similarities and differences between modules?
ES6 Module and CommonJS Module
- CommonJS is a shallow copy of a Module. ES6 Module is a reference to a Module. ES6 Module is read-only only and cannot be changed.
- The import interface is read-only and cannot be modified. You cannot change the pointer to the variable, but you can change the pointer to the variable. You can reassign commonJS (change the pointer to), but assignment to ES6 Module will compile error.
What ES6 Module and CommonJS Module have in common:
- Both CommonJS and ES6 Modules can assign values to imported objects, that is, change the values of the internal properties of the object.
20. What are common DOM operations
1) Obtain the DOM node
DOM node API and usage:
getElementById // Query by ID
getElementsByTagName // Query by label name
getElementsByClassName // Query by class name
querySelectorAll // Query by CSS selector
// Query by ID
var imooc = document.getElementById('imooc') // Query the element whose ID is iMOOc
// Query by label name
var pList = document.getElementsByTagName('p') // Query the set labeled p
console.log(divList.length)
console.log(divList[0])
// Query by class name
var moocList = document.getElementsByClassName('mooc') // Query a collection of classes named MOOC
// Query by CSS selector
var pList = document.querySelectorAll('.mooc') // Query a collection of classes named MOOC
Copy the code
2) DOM node creation
Creates a new node and adds it to the specified node. The known HTML structure is as follows:
<html>
<head>
<title>DEMO</title>
</head>
<body>
<div id="container">
<h1 id="title">I am heading</h1>
</div>
</body>
</html>
Copy the code
To add a content span node to the title node, do the following:
// Get the parent node first
var container = document.getElementById('container')
// Create a new node
var targetSpan = document.createElement('span')
// Set the contents of the span node
targetSpan.innerHTML = 'hello world'
// Insert the newly created element into the parent node
container.appendChild(targetSpan)
Copy the code
3) DOM node deletion
Delete the specified DOM node. The known HTML structure is as follows:
<html>
<head>
<title>DEMO</title>
</head>
<body>
<div id="container">
<h1 id="title">I am heading</h1>
</div>
</body>
</html>
Copy the code
To delete the element whose ID is title, do this:
// Get the parent element of the target element
var container = document.getElementById('container')
// Get the target element
var targetNode = document.getElementById('title')
// Delete the target element
container.removeChild(targetNode)
Copy the code
Or do it through an array of child nodes:
Var container = document.getelementById ('container') var targetNode = container.childNodes[1]// Remove the target element container.removechild (targetNode)
Copy the code
4) Modify DOM elements
The action of modifying a DOM element can be divided into many dimensions, such as moving the position of the DOM element, modifying the properties of the DOM element, and so on.
Swap the positions of the two specified DOM elements. The known HTML structure is as follows:
<html>
<head>
<title>DEMO</title>
</head>
<body>
<div id="container">
<h1 id="title">I am heading</h1>
<p id="content">I am content</p>
</div>
</body>
</html>
Copy the code
Now to swap title and content, consider insertBefore or appendChild:
// Get the parent element
var container = document.getElementById('container')
// Get two elements to be swapped
var title = document.getElementById('title')
var content = document.getElementById('content')
// Swap the two elements, putting content before title
container.insertBefore(content, title)
Copy the code
21. What does it mean to use strict? What’s the difference in using it?
Use Strict is a mode added by ECMAscript5 that allows Javascript to run under more stringent conditions. The objectives of the strict model are as follows:
- Eliminate Javascript syntax is not reasonable, not rigorous place, reduce weird behavior;
- Eliminate the unsafe place of code running, ensure the safety of code running;
- Improve the compiler efficiency and increase the running speed;
- Laying the groundwork for future versions of Javascript.
The difference between:
- Disallow the with statement.
- Disallow the this keyword to point to global objects.
- Objects cannot have properties of the same name.
22. How to determine whether an object belongs to a class?
- In the first, we use the instanceof operator to determine whether the constructor’s prototype property appears anywhere in the object’s prototype chain.
- The second way to judge is through the constructor property of the object, which points to the constructor of the object, but this is not very safe because the constructor property can be overwritten.
- The third way, if you need to determine is a built-in reference type, you can use the Object. The prototype, the toString () method to print the Object’s [[Class]] attribute to determine.
23. The difference between strongly typed and weakly typed languages
- Strongly typed language: A strongly typed language, also known as a strongly typed definition language, is a language that always enforces type definition, requiring that the use of variables be strictly defined, and that all variables must be defined before they are used. Languages such as Java and C++ are typed compulsively, meaning that once a variable is specified to a data type, it will always be that data type if it is not cast. For example, if you have an integer, you cannot treat it as a string without explicitly converting it.
- Weakly typed languages: Weakly typed languages are also known as weakly typed defined languages, as opposed to strongly typed defined languages. The JavaScript language is a weakly typed language. A language in which variable types can be ignored. For example, JavaScript is weakly typed. In JavaScript, you can concatenate the string ’12’ to the integer 3 to get the string ‘123’, which will be cast when added.
Contrast: A strongly typed language may not be as fast as a weakly typed language, but the rigor of a strongly typed language can effectively help avoid many mistakes.
24. Differences between interpreted and compiled languages
(1) Interpreted languages use specialized interpreters to translate the source program line by line into platform-specific machine code and execute it immediately. Code is translated and executed line by line dynamically by the interpreter at execution time, rather than before execution. Interpreted languages do not require prior compilation; they interpret source code directly into machine code and execute it immediately, so a program can be run as long as a platform provides an interpreter. Its characteristics are summarized as follows
- Interpreted language needs to interpret the source code into machine code and execute each time, which is inefficient.
- As long as the platform provides the corresponding interpreter, the source code can be run, so it is easy to migrate the source program;
- JavaScript and Python are interpreted languages.
(2) Compiled languages use specialized compilers to compile high-level language source code into machine code that can be executed by the platform hardware at one time for a specific platform, and package it into executable program format that can be recognized by the platform. Before the program written in the compiled language is executed, a special compilation process is required to compile the source code into a machine language file, such as the FILE in the format of EXE. Later, when you want to run again, you can directly use the compiled results, such as the direct run exe file. Compiled languages perform more efficiently because they only need to be compiled once and don’t need to be compiled at run time. Its characteristics are summarized as follows:
- It can be compiled into platform-related machine language files at one time, leaving the development environment at runtime and running efficiently.
- Platform-specific and generally not portable to other platforms;
- C and C++ are compiled languages.
The main difference is that the former is run on the platform when the source program is compiled, while the latter is compiled during runtime. So the former is fast and the latter is cross-platform.
25. for… In and for… The difference of
The for… “Of” is a new iterator in ES6 that allows you to iterate over a data structure (array, object, etc.) containing an iterator interface and return the values of each item, as well as for… The difference in is as follows
- The for… The of traversal retrives the key of the object, for… In gets the key name of the object;
- The for… In traverses the entire prototype chain of objects and is not recommended for poor performance, whereas for… Of only traverses the current object and does not traverse the prototype chain;
- For an array traversal, for… In returns all enumerable properties in the array (including those on the prototype chain), for… Of only returns the value of the attribute corresponding to the index of the array;
Conclusion: the for… In loops are designed primarily to iterate over objects, not groups; for… The of loop can be used to traverse arrays, array-like objects, strings, sets, maps, and Generator objects.
How to use for… Of traverses the object
The for… “Of” is a new iterator in ES6 that allows you to iterate over a data structure (array, object, etc.) that contains an iterator interface and return the values of each item. Of traversal is an error.
If the object you want to iterate over is an array-like object, use array. from to convert it to an Array.
var obj = {
0:'one'.1:'two'.length: 2
};
obj = Array.from(obj);
for(var k of obj){
console.log(k)
}
Copy the code
If it is not an array-like object, add a [Symbol. Iterator] property to the object and point to an iterator.
// Method 1:
var obj = {
a:1.b:2.c:3
};
obj[Symbol.iterator] = function(){
var keys = Object.keys(this);
var count = 0;
return {
next(){
if(count<keys.length){
return {value: obj[keys[count++]],done:false};
}else{
return {value:undefined.done:true}; }}}};for(var k of obj){
console.log(k);
}
/ / method 2
var obj = {
a:1.b:2.c:3
};
obj[Symbol.iterator] = function* (){
var keys = Object.keys(obj);
for(var k of keys){
yield [k,obj[k]]
}
};
for(var [k,v] of obj){
console.log(k,v);
}
Copy the code
27. The difference between Ajax, Axios and FETCH
(1) the AJAX AJAX “AsynchronousJavascriptAndXML” (asynchronous JavaScript and XML), is a web development technology to create interactive web applications. It is a technology that can update parts of a web page without having to reload the entire page. Ajax enables web pages to be updated asynchronously by exchanging small amounts of data with the server in the background. This means that parts of a page can be updated without reloading the entire page. Traditional web pages (which do not use Ajax) must reload the entire page if they need to update their content. Its disadvantages are as follows:
- Itself is designed for MVC programming and does not fit the wave of front-end MVVM
- Based on native XHR development, the architecture of XHR itself is unclear
- Does not conform to the principle of Separation of Concerns
- Configuration and invocation are confusing, and the event-based asynchronous model is unfriendly.
Fetch, billed as an AJAX alternative, was introduced in ES6, using promise objects from ES6. Fetch is based on promise. Fetch’s code structure is much simpler than Ajax. Fetch is not a further encapsulation of Ajax, but native JS without using the XMLHttpRequest object.
Advantages of FETCH:
- The syntax is concise and more semantic
- Based on standard Promise implementation, support async/await
- Lower level, rich API (Request, Response)
- XHR is a new implementation in the ES specification
Disadvantages of FETCH:
- The FETCH is rejected only for network requests. The server does not reject requests with 400 or 500 error codes. The FETCH is rejected only when the request cannot be completed because of network errors.
- Fetch (URL, {credentials: ‘include’})
- Fetch does not support abort and timeout control. Timeout control implemented with setTimeout and promise. reject does not prevent the request process from running in the background, resulting in wasted traffic
- Fetch has no way to natively monitor the progress of requests, whereas XHR can
Axios is an HTTP client based on Promise encapsulation. It has the following features:
- The browser initiates XMLHttpRequests
- The node sends an HTTP request
- Supporting Promise API
- Listen for requests and returns
- Convert the request and return
- Cancel the request
- Automatically convert JSON data
- The client can resist XSRF attacks
28. What are the methods of array traversal
methods | Whether to change the array | The characteristics of |
---|---|---|
forEach() | no | Array method, does not change the original array, does not return a value |
map() | no | Array method, does not change the original array, has a return value, can be called chain |
filter() | no | Array method, which filters an array and returns an array containing qualified elements, can be called chained |
for… of | no | for… Of iterates over the properties of an object that has an Iterator, returning the values of the elements of the array, the properties of the object, and not traversing ordinary obj objects |
Every () and some () | no | Array methods, some(), return true as long as either of them is true; Every () returns false as long as one of them is false. |
The find () and findIndex () | no | The array method, find(), returns the first value that meets the criteria; FindIndex () returns the index of the value of the first return condition |
Reduce () and reduceRight () | no | Array method, reduce() on the array of positive order operation; ReduceRight () inverts the array |
A detailed explanation of traversal methods: Counting those Traversals and loops in JavaScript
29. What’s the difference between forEach and map methods
Both of these methods are used to traverse groups of numbers, and the difference between them is as follows:
- The forEach() method executes the provided function on each element. The operation on the data changes the array. The method returns no value;
- The map() method does not change the value of the original array, and returns a new array with the same value as the one that was processed by the function that called the original array.
Prototypes and prototype chains
1. Understanding of prototypes and prototype chains
In JavaScript, constructors are used to create new objects. Each constructor has a Prototype property inside, and its property value is an object containing properties and methods that can be shared by all instances of the constructor. When a new object is created using the constructor, it contains a pointer to the value of the constructor’s prototype property. In ES5, this pointer is called the object’s prototype. Generally you should not be able to get this value, but browsers now implement the proto property to access this property, but it is best not to use this property because it is not specified in the specification. ES5 has added an object.getPrototypeof () method that allows you to get the prototype of an Object.
When you access a property of an object, if the property doesn’t exist inside the object, then it will look for that property in its prototype object, and that prototype object will have its own prototype, and so on and so forth, the concept of a chain of prototypes. The end of the prototype chain is usually object.prototype, so that’s why new objects can use methods like toString().
Features:JavaScript objects are passed by reference, and each new object entity created does not have its own copy of the prototype. When you modify the prototype, the objects associated with it inherit the change.
2. Prototype modification and rewrite
function Person(name) {
this.name = name
}
// Modify the prototype
Person.prototype.getName = function() {}
var p = new Person('hello')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // true
// Rewrite the prototype
Person.prototype = {
getName: function() {}}var p = new Person('hello')
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // false
Copy the code
You can see that the p constructor doesn’t point to Person when we change the stereotype, because when we directly assign the Object to the stereotype of Person, its constructor points to the root constructor Object, so p.constructor === Object, Instead of P.communstructor === Person. To be true, use constructor:
Person.prototype = {
getName: function() {}}var p = new Person('hello')
p.constructor = Person
console.log(p.__proto__ === Person.prototype) // true
console.log(p.__proto__ === p.constructor.prototype) // true
Copy the code
3. Prototype chain pointing
p.__proto__ // Person.prototype
Person.prototype.__proto__ // Object.prototype
p.__proto__.__proto__ //Object.prototype
p.__proto__.constructor.prototype.__proto__ // Object.prototype
Person.prototype.constructor.prototype.__proto__ // Object.prototype
p1.__proto__.constructor // Person
Person.prototype.constructor // Person
Copy the code
4. Where does the prototype chain end? How do I print the end of the prototype chain?
Due to theObject
Is the constructor, and the prototype chain ends atObject.prototype.__proto__
And theObject.prototype.__proto__=== null // true
So, the end of the prototype chain isnull
. All prototypes in the prototype chain are objects, and all objects are ultimately made byObject
Structural, andObject.prototype
The next level of PI is PIObject.prototype.__proto__
.
5. How do I get properties on objects that are not on the stereotype chain?
Use the post-hasownProperty () method to determine whether a property belongs to the stereotype chain:
function iterate(obj){
var res=[];
for(var key in obj){
if(obj.hasOwnProperty(key))
res.push(key+':'+obj[key]);
}
return res;
}
Copy the code
Execute context/scope chains/closures
1. Understanding closures
A closure is a function that has access to variables in the scope of another function. The most common way to create a closure is to create another function within a function that has access to variables local to the current function.
Closures have two common uses;
- The first use of closures is to enable us to access variables inside the function from outside. Using closures, you can externally access variables inside the function by calling the closure function externally, and you can use this method to create private variables.
- Another use of closures is to keep a variable object in the context of a function that has finished running in memory because the closure function retains a reference to the variable object, so the variable object is not reclaimed.
For example, if function A has A function B inside it that can access variables in function A, then function B is A closure.
function A() {
let a = 1
window.B = function () {
console.log(a)
}
}
A()
B() / / 1
Copy the code
In JS, closures exist to give you indirect access to variables inside a function. Use closures in a loop to solve the problem of var defining functions
for (var i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i)
}, i * 1000)}Copy the code
First of all, since setTimeout is an asynchronous function, it will execute the entire loop first, and then I will be 6, so it will print a bunch of 6’s. There are three solutions:
- The first is using closures
for (var i = 1; i <= 5; i++) { ; (function(j) { setTimeout(function timer() { console.log(j) }, j * 1000) })(i)}
Copy the code
In the above code, we first use the immediate execution function to pass I into the function. At this time, the value is fixed on the parameter j and will not change. The next time we execute the timer closure, we can use the variable j of the external function to achieve this purpose.
- The second is use
setTimeout
The third argument to thetimer
Function parameters are passed in.
for (var i = 1; i <= 5; i++) {
setTimeout(
function timer(j) {
console.log(j)
},
i * 1000,
i
)
}
Copy the code
- The third is use
let
definei
To solve the problem, this is the most recommended way
for (let i = 1; i <= 5; i++) {
setTimeout(function timer() {
console.log(i)
}, i * 1000)}Copy the code
2. Understanding of scope and scope chain
1) Global scope and function scope
(1) Global scope
- Outermost functions and variables defined outside them have global scope
- All variables with no direct assignment defined are automatically declared to global scope
- All properties of window objects have global scope
- The global scope has many disadvantages. Too many variables in the global scope will pollute the global namespace and cause naming conflicts.
(2) Function scope
- The zeroing of a function scope declaration within a function, usually accessible only to fixed snippets of code
- Scopes are layered; inner scopes can access outer scopes, and vice versa
2) Block-level scope
- Block-level scopes can be declared using the new let and const directives in ES6. Block-level scopes can be created in a function or in a block of code
{}
Package snippets) - Variables declared as let and const do not have variable promotion and cannot be declared repeatedly
- A good place to bind block-level scope is within a loop, which limits the declared counter variables to within the loop.
Scope chain: find the required variable in the current scope, but the scope does not have the variable, then the variable is free. If you cannot find the variable in your own scope, you go to the parent scope, and then to the upper scope, until you access the Window object, and then it is terminated. This layer of relationship is called the scope chain.
The purpose of the scope chain is to ensure orderly access to all variables and functions that the execution environment has access to. Through the scope chain, variables and functions in the outer environment can be accessed.
The scope chain is essentially a list of Pointers to variable objects. A variable object is an object that contains all the variables and functions in the execution environment. The front end of the scope chain is always a variable object for the current execution context. The variable object of the global execution context (that is, the global object) is always the last object in the scope chain.
When looking for a variable, you can look backward down the scope chain if it is not found in the current execution environment.
3. Understanding the execution context
1. The execution context type
(1) Global execution context
Anything that is not inside a function is a global execution context. It first creates a global window object and sets the value of this to be equal to that global object. There is only one global execution context in a program.
(2) Function execution context
When a function is called, a new execution context is created for that function, which can have any number of contexts.
(3) The execution context of the eval function
Code that executes in the eval function has its own execution context, but the eval function is infrequently used and will not be covered.
2. Execute context stack
- The JavaScript engine uses the execution context stack to manage the execution context
- When JavaScript code is executed, the first global code, will create a global execution context and pressure into the execution stack, whenever a function call, will create a new execution context for the function and pressure into the stack, the engine will execute in the execution context function, on the top of the stack when the function is completed, the execution context pop up from the stack, Proceed to the next context. When all the code has been executed, the global execution context is popped off the stack.
let a = 'Hello World! ';
function first() {
console.log('Inside first function');
second();
console.log('Again inside first function');
}
function second() {
console.log('Inside second function');
}
first();
// Order of execution
Second (); first();
Copy the code
3. Create an execution context
Creating an execution context has two phases: the creation phase and the execution phase
1) The creation phase
(1) This binding
- In the context of global execution, this points to the global object (window object)
- In the context of a function execution, this points to depending on how the function is called. If it is called by a reference object, then this is set to that object, otherwise the value of this is set to global or undefined
(2) Create lexical environment components
- A lexical environment is a data structure with identifiers — variable mappings, where identifiers are variable/function names, and variables are references to actual objects or raw data.
- Inside the lexical environment there are two components: bold style: environment logger: a reference to the external environment used to store the actual location of variable function declarations: parent scope accessible
(3) Create variable environment components
- The variable environment is also a lexical environment, and its environment logger holds the bindings created by the variable declaration statement in the execution context.
2) Execution phase This phase will complete the allocation of variables and finally execute the code.
Simply put, an execution context is:
Before executing a bit of JS code, you need to parse the code. When parsing, it will first create a global execution context. It will first take out variables and function declarations that will be executed in the code, and assign variables to undefined, and declare functions to be used first. After this step is completed, the formal execution procedure begins.
Before a function is executed, a function execution context is also created, similar to the global execution context, except that the function execution context includes this, arguments, and function arguments.
- Global context: variable definition, function declaration
- Function context: variable definition, function declaration,
this
.arguments
Note: Due to the word limit, the rest of the content will be summarized in the next part.