JavaScript related interview questions


Why is javascript single threaded?

If js is multithreaded and multiple threads operate on DOM elements at the same time, which thread is the main one is a problem

The new HTML5 standard allows the use of new Worker to start a new thread to run a separate js file script, but the new thread strictly requires the functions that can be used. For example, it can only use ECMAScript and cannot access Dom and BOM. This limits the possibility of multiple threads operating DOM elements at the same time

data type

How many data types are there?


Raw data type:
-  Boolean type: Boolean represents a logical entity and can have two values: true and false. 
-  Null Type: Null Type has only one value: null. 
-  Undefined Type: a variable that is not assigned a value will have a default value undefined. 
-  Number type: according to ECMAScript Standards, JavaScript There is only one number type in: Based on IEEE 754 Values in standard double precision 64 bit binary format(-(253 -1) To 253 -1). It does not give a specific type for integers. In addition to being able to represent floating-point numbers, there are some signed values:+Infinity,-Infinity and NaN (Non numeric, Not-a-Number). 
-  BigInt Type: BigInt Type is JavaScript A basic numeric type in which integers can be expressed with any precision. use BigInt,You can safely store and manipulate large integers, even exceeding the safe integer limit of numbers. BigInt Is by appending n Or call the constructor to create.
-  String String type: JavaScript The string type of is used to represent text data. It is the "element" of a set of 16 bit unsigned integer values. Each element in the string occupies the position of the string. The index of the first element is 0, the next is index 1, and so on. The length of a string is the number of its elements.
- Symbols Symbol types: Symbols(Symbols)yes ECMAScript New definitions in the 6th Edition. The symbol type is unique and cannot be modified, And can also be used as Object of key Value of(as follows). There are similar atomic types in some languages(Atoms). You can also think of them as C Inside the enumeration type.
Reference data type:
- Object Objects: in Computer Science, An object is an area of memory that can be referenced by an identifier.

The difference between stack and pair

  • Stack

Stack features: first in and last out. It is mainly exclusive to one thread and serves the function call of this thread. It is used to store the return address and temporary variables. The memory of the stack is generally allocated and released by the compiler itself. The memory allocated by the compiler is continuous. When defining a variable, the memory of the variable of the heart is allocated at the end of the current stack area. The stack size is 2M in windows system and 8M in linux system. ulimit-s can be used to set the stack size. The allocation of stack space is from high address to low address.

  • heap

The heap is allocated and released by the programmer. In windows system, it is generally less than 2G. Because the system uses the linked list to realize the free address space, the memory space of the heap is not continuous, and the traversal of the linked list is also from low address to high address, so the allocated memory is also allocated from low address to high address.

What types does Object contain?

It includes Date, function, Array, etc. These three are conventional.

What are the typeof outputs in JS

{}, [] output object.

console.log output function.

console.log() output undefined

Number('as') == NaN?

Although Number('as') outputs NaN.

But the output of this is false

Because js specifies that NaN is not equal to any value, including NaN

isNaN() needs to be used to judge whether it is NaN or not

What's the difference between null and undefined

Null has only one value and is null. Object that does not exist.

Undefined has only one value, which is undefined. Not initialized. Undefined is derived from null.

The simple understanding is: undefined is undefined, null is defined but empty.

What is the reason why null does not exist? How to solve it?

Non existent reason

  1. Method does not exist
  2. Object does not exist
  3. String variable does not exist
  4. Interface type object not initialized

Solution: when making judgment, put it in front of the set value

How to judge the data type

  1. typeof

    typeof null  // object
    typeof undefined // undefined
    typeof [] //object
    typeof console.log // function
    typeof console.log() //undefined
    typeof 1 // number
    typeof "1" //string
  2. instanceof

    Principle: A instanceof B can judge whether A is an instance of B, return A Boolean value, and judge the data type from the construction type

    console.log(arr instanceof Array ); // true
    console.log(date instanceof Date ); // true
    console.log(fn instanceof Function ); // true
    //Note: the instanceof must be followed by an object type, and the case cannot be misspelled. This method tries some conditional selection or branching
  3. . through toString under Object Call () method to determine;
    console.log(; //[object Number]
    console.log('123')); //[object String]
    console.log(; //[object Undefined]
    console.log(; //[object Boolean]
    console.log({})); //[object Object]
    console.log([])); //[object Array]
    console.log({})); //[object Function]
  4. constructor judgment of root object

    console.log('Data type judgment' -  constructor);
    console.log(arr.constructor === Array); //true
    console.log(date.constructor === Date); //true
    console.log(fn.constructor === Function); //true
  5. jQuery's method $ isArray()

How to judge the data type

Determine whether it is an array

typeof cannot be used to judge an array

typeof array returns object

  1. Array.isArray(arr)
  2. arr.constructor === Array
  3.,-1) = = = 'array' or toString call(arr) === ‘[object Array]’
  4. arr instanceof Array
  5. arr.__proto__ === Array.prototype and instanceof are the same in principle
  6. jQuery's method $ isArray()


==Convert the type first and then compare, = = = judge the type first. If it is not the same type, it is directly false.
===The two sides of the comparison should be absolutely the same

alert(0 == ""); // true
alert(0 == false); // true
alert("" == false); // true

alert(0 === ""); // false
alert(0 === false); // false
alert("" === false); // false

Let's start with = = = strictly equal to. This is relatively simple. The specific comparison rules are as follows:

1. If the types are different, they are [unequal]
2. If both are numeric values and the same value, then [equal]; (! Exception) is that if at least one of them is NaN, then [unequal]. (whether a value is NaN can only be judged by isNaN())
3. If both are strings and the characters in each position are the same, then [equal]; Otherwise [unequal].
4. If both values are true or both are false, then [equal].
5. If both values refer to the same object or function, [equal]; Otherwise [unequal].
6. If both values are null or undefined, then [equal].

Besides = =, the specific comparison rules are as follows:

1. If the two values are of the same type, a = = = comparison is performed. The comparison rules are the same as above
2. If two value types are different, they may be equal. Perform type conversion and comparison according to the following rules:
a. If one is null and the other is undefined, then [equal].
b. If one is a string and the other is a value, convert the string into a value and compare it.
c. If any value is true, convert it to 1 and compare it; If any value is false, convert it to 0 and compare it.
d. If one is an object and the other is a value or string, convert the object to the value of the basic type and compare it. Object is converted to the base type, using its toString or valueOf methods. js core built-in class, will try valueOf before toString; The exception is Date, which uses toString conversion. Non js core objects, Ling said (it's troublesome and I don't understand it)
e. Any other combination (array, array, etc.) is [unequal].

Double equal sign comparison rule

If the types are different, type conversion is performed

  1. If an operand is a Boolean value, convert it to a numeric value before checking for equality. false is converted to 0 and true to 1.
  2. If one operand is a string and the other is a number, try converting the string to a number before checking for equality.
  3. If one operand is an object and the other is a string, try to convert the object to a string (call the toString() method) before checking the equality.
  4. If one operand is an object and the other is a number, try converting the object to a number before checking for equality.

The operator also follows the following rules when comparing

  1. Values null and undefined are equal.
  2. null and undefined cannot be converted to other values when checking equality.
  3. If an operand is NaN, the equal sign returns false and the non equal sign returns true. Important: even if both operands are NaN, the equal sign returns false because NaN is not equal to NaN according to the rule.
  4. If both operands are objects, their reference values are compared. If two operands point to the same object, the equal sign returns true, otherwise the two operands are not equal.

if statement judgment rule

An expression with a value of true or false. If necessary, non Boolean expressions can also be converted to Boolean values, but the following rules should be followed:
All objects are treated as true.
If and only if the string is empty, the string is treated as false.
null and undefined are treated as false.
If and only if the number is zero, the number is treated as false.

Difference between undefine and null

null means there is no object, that is, there should be no value there

As a parameter of a function, it means that the parameter of the function is not an object

As the end of the object prototype chain

undefined means the value is missing, that is, there should be a value here, but it is not defined

If a formal parameter is defined but no argument is passed, it is displayed as undefined

undefined is displayed when the object property name does not exist

The function does not write the return value, that is, it does not write return. It gets undefined

Write a return, but do not assign a value. You get undefined

null and undefined are converted to number data types

null defaults to 0

undefined is changed to NaN by default

number maximum range

The absolute value is less than the 53rd power of 2

Prototype chains and prototype objects

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-3T7QzQm9-1641822732979)(image/20190311194017886.png)]

prototype and__ proto__ And constructor This article is very clear

Prototype object prototype

All JavaScript objects inherit properties and methods from a prototype.

What prototype chain

All objects in JavaScript are located in JavaScript objects, and there is a chain pointing to a prototype Object. When trying to access the properties of an Object, it searches not only on the Object, but also the prototype of the Object and the prototype of the prototype of the Object. It searches up layer by layer until it finds an attribute with matching name or reaches the end of the prototype chain. An instance of the Object at the top of the prototype chain.


a instanceof A

instanceof is an instance that can be used to judge whether a variable belongs to an object. instanceof detects who the prototype of the variable belongs to.

  • The judgment rule of instanceof is to look up along the prototype attribute of Func. If the same reference can be found, it will return true, otherwise it will return false.
  • Each function has a prototype attribute (the prototype object is stored), and each prototype object has a proto (implicit prototype) pointing to the prototype object (prototype) of its constructor. Object has no prototype attribute.

[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-YZNF7V5J-1641822732980)(image/20210107170912701.jpg)]

  • func._ proto_ Point to func prototype
  • Func._ proto_ Point to object prototype
  • Finally, it points to Object, which also verifies the idea that everything is an Object. Therefore, the return result of func instanceof Function and func instanceof Object is true, and the return result of func instanceof Function is false.

The instanceof operator actually checks the elements on the left__ proto__ There is no prototype of the right class or object on the chain.
Similarly, when so and so is an instance of so and so, it is actually proved__ proto__ There is a prototype of the right class or object on the chain.

Limitations of instanceof

(1) instanceof cannot directly determine the original data type

var str1 = 'hello word';
var str2 = new String('hello world');
console.log(str1 instanceof String);		//false
console.log(str2 instanceof String);		//true

We can solve this problem as follows:

class PrimitiveString{
	static [Symbol.hasInstance](x){
		return typeof x === 'string'
console.log('hello world' instanceof PrimitiveString);		//true

Symbol.hasInstance can be understood as a method to customize instanceof behavior. The function of the above code is equal to typeof ('hello world '= = = =' string ').

(2) instanceof cannot judge a special type

console.log(new Date() instanceof Date);		//true
console.log(new Date() instanceof Object);		//true
console.log([] instanceof Array);		//true
console.log([] instanceof Object);		//true

instanceof can only be used to judge whether two objects belong to the instance relationship, but not the type of a is.

High energy! typeof Function. Discussion on function or Object triggered by prototype

function F(){};
var o = {};
typeof F;                          //==> function
typeof o;                          //==> object
typeof F.prototype;                //==> object
typeof o.prototype;                //==> undefinded
typeof new F;                      //==> object
typeof (new F).prototype;          //==> undefined
typeof (new F).__proto__;          //==> object
typeof F.__proto__;                //==> function
typeof o.__proto__;                //==> object
typeof Object;                     //==> function
typeof Function;                   //==> function
typeof (new Function).prototype;   //==> object
typeof (new Function).__proto__;   //==> function
typeof (new Object).prototype;     //==> undefined
typeof (new Object).__proto__;     //==> object
typeof Object.prototype;           //==> object
typeof Object.__proto__;           //==> function
typeof Function.prototype;         //==> function
typeof Function.__proto__;         //==> function	

Original link

Write a prototype chain of an empty array

console.log(typeof [].__proto__)

Object(0) []
[Object: null prototype] {} 

So the prototype chain of an empty array first points to Array.prototype Then point Object.prototype Then point null


js is single threaded

What is Promise

  1. It is mainly used for asynchronous computing
  2. You can queue asynchronous operations, execute them in the desired order, and return the expected results
  3. promise can be passed and manipulated between objects to help us deal with queues


  • promise is an object. The difference between an object and a function is that an object can save state, but a function cannot (except closures)
  • It does not deprive the function of return, so there is no need to pass callback layer by layer to get data
  • Code style, easy to understand and easy to maintain
  • Multiple asynchronous wait merges are easy to solve
new Promise(
  function (resolve, reject) {
    // A time-consuming asynchronous operation
    resolve('success') // Data processing completed
    // reject('failed ') / / data processing error
  (res) => {console.log(res)},  // success
  (err) => {console.log(err)} // fail
  • promise has three states:
    1. pending initial status
    2. [implemented] operation succeeded
    3. rejected operation failed
    When the promise state changes, the response function in then() will be triggered to process the subsequent steps;
    Once the promise state is changed, it will not change again.
  • resolve is used to change the state of Promise object from "incomplete" to "successful" (that is, from pending to resolved). It is called when the asynchronous operation is successful, and the result of the asynchronous operation is passed as a parameter;
    reject is used to change the state of the Promise object from incomplete to failed (that is, from pending to rejected), call when the asynchronous operation fails, and pass the errors reported by the asynchronous operation as parameters.
  • There are only two possibilities for the state of Promise object to change:
    From pending to fulfilled
    From pending to rejected.
    As long as these two situations occur, the state solidifies and will not change again.

Conclusion: promise is the most important feature of a queue. After we generate a promise queue anywhere, we can pass it as a variable to other places.

If in What happens if the function of then() does not return a new promise?


1. Receive two functions as parameters, representing completed and rejected respectively
2,. then() returns a new Promise instance, so it can be called chained
3. When the previous Promise state changes then() selects a specific state response function to execute according to its final state
4. The state response function can return a new promise or other value. If it does not return a value, we can think that it returns a null;
5. If a new promise is returned, the next level is returned then() is executed after the new promise state changes
6. If any other value is returned, the next level is executed immediately then()

Common usage:

Asynchronous operation and timer are put together. If the timer is triggered first, it will be considered as timeout and inform the user;
For example, we need to load resources from a remote service home. If 5000ms has not been loaded, we will inform the user that the loading failed

Usage in reality
The callback is packaged as Promise, which has two obvious benefits:
1. Good readability
2. The returned results can be added to any Promise queue

Tear promise by hand all

Recursive implementation

function diyPromiseAll(arr) {
    // This is an array that holds the return value
    let res_arr = [];
    // This is the subscript of promise currently traversed
    let currentPromiseIndx = 0;
    return new Promise((resolve, reject) => {
        // This is almost a recursive function. If you don't traverse to the last promise, you will recurse uniformly to the last promise
        function dealPromise(){
            if (currentPromiseIndx === arr.length - 1) {
                arr[currentPromiseIndx].then(res => {
            } else {
                arr[currentPromiseIndx].then(res => {

async and await

Effects of async and awati on reduce and map

Event loop EventLoop

Macro and micro tasks


  • Title:

    • Output the following operation results
    • The correct output is: 3 3 4 4 5 2 2 7
  • thinking

    • Step 1: output the synchronous Promise instance as synchronous output
    • Part II: output Promise then
    • Part 3: output setTimeout
  let int = 1;
  setTimeout(function() {
    console.log(int) // 5th output
    int = 2
    new Promise((resolve, reject) => {
    }).then(function() {
      console.log(int) // 2nd 7th output
      int = 7
    console.log(int) // 2nd 6th output
  int = 3
  console.log(int) // 3 1st output
  new Promise((resolve, reject) => {
    console.log(int) // 3th output
    return resolve(int = 4)
  }).then(function(res) {
    console.log(int) // 4th output
    int = 5
    setTimeout(function() {
      console.log(int) // 78th output
      int = 8
    return false

  console.log(int) // 4 3rd output


What are the new features of ES6?

  1. let,const
  2. Arrow function
  3. The data type symbol is added
  4. Destructuring assignment
  5. rest...
  6. Array adds a new method isarray, array from
  7. Object.assign
  8. class keyword
  9. Promise asynchronous operation
  10. iterable iterator
  11. Generator generator
  12. for...of
  13. Map,Set

The difference between var, let and const

  1. Variables declared by var will be mounted on window, while variables declared by let and const will not;
var a = 100;
console.log(a, window.a);    // 100 100

let b = 10;
console.log(b, window.b);    // 10 undefined

const c = 1;
console.log(c, window.c);    // 1 undefined
  1. var declares that variables have variable promotion, while let and const do not
console.log(a);    // undefined variable promotion, declared unassigned
var a = 100;

console.log(b);    // Error: cannot access' a 'before initialization
let b = 10;

console.log(c);    // Error: cannot access' a 'before initialization
const c = 1;
  1. var has no block level scope, while let and const have block level scope
if(true) {
    var a = 100;
    let b = 200; 
console.log(a); // 100
console.log(b); // Error: B is not defined
  1. let and const cannot declare variables with the same name under the same scope, but var can
var a = 20;
var a = 30;
console.log(a); // 30
let b = 10;
let b = 5;
console.log(b); // Unexpected syntax error: identifier 'B' has already been declared
  1. let and const will have temporary dead zones, but var will not
var a = 10;
if(true) {
   console.log(a); // 10
   var a = 50;
if(true) {
   console.log(a); // Error: cannot access' a 'before initialization
   let a = 500;
  1. const declares a constant
    • null placeholders cannot be used once a declaration must be assigned.
    • Cannot be modified after declaration.
    • If you declare reference type data, you can modify its properties, but you cannot modify the reference.

Array object


  • constructor returns the prototype function that creates the array object.
  • length sets or returns the number of array elements.
  • prototype allows you to add properties or methods to array objects.

1.concat() connects two or more arrays and returns the result

The concat() method is used to join two or more arrays.

This method does not change the existing array, but only returns a copy of the connected array.

[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-2epE6DmO-1641822732981)(image/image-20210331234635891.png)]

2.every checks whether each element of the value element meets the conditions

The every() method is used to detect whether all elements of the array meet the specified conditions (provided by the function).

The every() method detects all elements in the array using the specified function:

  • If an element in the array is detected to be unsatisfactory, the entire expression returns false and the remaining elements will not be detected.
  • Returns true if all elements meet the criteria.

every() does not change the original array.

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-Z0EQF6WX-1641822732983)(image/image-20210331234855910.png)]


Fill the array with fixed values: change the original array

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-Gm1zhGjY-1641822732984)(image/image-20210331234930357.png)]


The filter() method creates a new array. The elements in the new array are checked by checking all the qualified elements in the specified array.




















Will change the of the original array (mutation method)

Add element class: (return new length)

  • push() adds an element to the end of the array
  • unshift() adds an element to the array header

Delete element class: (returns the deleted element)

  • pop() removes the last element of the array
  • shift() deletes the first element of the array

Reverse order:

  • reverse() reverses the order of elements in the original array

Insert, delete and replace array elements: (return the deleted array)

  • splice(index, howmany, item1...intemx)
    Index represents the index value of the array position to be manipulated. It is required
    howmany represents the number of elements to be deleted. It must be a number, which can be 0. If it is not filled in, it will be deleted from index to the end of the array
    item1... intemx represents the new value to be added to the array


  • sort() sorts the array elements

Do not change the of the original array

  • concat() connects two or more arrays and returns the result
  • every() checks whether each element in the array meets the requirements
  • some() detects whether any element in the array meets the requirements
  • filter() selects the qualified in the array and returns the qualified array
  • join() puts all the elements of the array into a string
  • toString() converts an array into a string
  • slice() intercepts an array and returns a new array
  • indexOf searches for an element in an array and returns its location
  • map
  • reduce

Higher order function


map() method: after each element in the original array calls a specified method, it returns a new array composed of return values.,index,arr), thisValue)


There is an array x=[1, 2, 3, 4, 5, 6, 7, 8, 9], find x^2

[the external link image transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the image and upload it directly (img-qgr4LBU2-1641822732985)(image/image-20210319175300515.png)]

function pow(x){  //Define a square function
    return x*x;

var arr=[1,2,3,4,5,6,7,8,9];
var result =;  //map() passes in the function object itself
console.log(result);       //Results: [1,4,9,16,25,36,49,64,81];


reduce() method: execute the callback function for each element in the array in turn (excluding the elements deleted or never assigned in the array), and return a specific result.

[x1, x2, x3, x4].reduce(f) = f(f(f(x1, x2), x3), x4)


array.reduce(function(total, currentValue, currentIndex, arr), initialValue)
  • callback (a function that executes each value in the array, including four parameters)
    • previousValue (the value of the first item or the result value of the previous superposition, or the initial value provided)
    • currentValue (the currently processed element in the array)
    • Index (the index of the current element in the array)
    • Array (array itself)
    • initialValue (as the first parameter of the first call to callback, you can control the format of the returned value)

Example 1: array summation

var  arr = [1, 2, 3, 4, 5];
sum = arr.reduce(function(prev, cur, index, arr) {
    console.log(prev, cur, index);   //The output is the value of the first item or the result of the last superposition, the element being processed and the index value of the element being processed
    return prev + cur;
console.log(arr, sum); //Enter the array itself and the final result

// Abbreviation
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {  //The callback function only passed in two parameters: previousValue and currentValue
    return x + y;
});               // Result: 25,initialValue defaults to 0

// Pass in an initial value
var arr = [1, 3, 5, 7, 9];
arr.reduce(function (x, y) {
    return x + y;
},10);               // Result: 35, becomes the sum of the initial value and the array

Example 2:

Instead of using JavaScript's built-in parseInt() function, implement a string2int() function using map and reduce operations
Idea: 1 First, change the string 13579 to Array -- [1, 3, 5, 7, 9]
2. Use reduce() to write a function that converts a string to Number.

function string2int(s) {
    var arr = s.split('').map(function(x){
        return +x;
    return arr.reduce(function(prev,res){
       return prev*10+res;
// Test:
if (string2int('0') === 0 && string2int('12345') === 12345 && string2int('12300') === 12300) {
    if (string2int.toString().indexOf('parseInt') !== -1) {
        console.log('Do not use parseInt()!');
    } else if (string2int.toString().indexOf('Number') !== -1) {
        console.log('Do not use Number()!');
    } else {
        console.log('Test passed!');
else {
    console.log('Test failed!');

tips: the + sign in front of the string can be quickly converted to number type

Four methods of converting string to number

  • Example 3 find the number of occurrences of each letter in a string

    var arrString = 'abcdaabc';
    arrString.split('').reduce(function(res, cur) {
        res[cur] ? res[cur] ++ : res[cur] = 1
        return res;
    }, {})
  • Example 4

    Please change the non-standard English name entered by the user into uppercase and other lowercase standard names.
    Input: ['adam ',' Lisa ',' Bart '], output: ['adam', 'Lisa', 'Bart'].

    function normalize(arr) {
           x=x.toLowerCase();   //Note that after converting x to lowercase, it should be re assigned to x, otherwise x will not change
           x=x[0].toUpperCase()+ x.substr(1); //substr(start,length) string segmentation. Start from start and intercept the length
           return x;
    // Test:
    if (normalize(['adam', 'LISA', 'barT']).toString() === ['Adam', 'Lisa', 'Bart'].toString()) {
        console.log('Test passed!');
    else {
        console.log('Test failed!');


Filter is also a common operation. It is used to filter out some elements of Array and then return the remaining elements.

Like map(), Array's filter() also receives a function. Unlike map(), filter() applies the passed function to each element in turn, and then decides whether to keep or discard the element according to whether the return value is true or false.

  • Example 1: select an even number

    var arr = [1, 2, 4, 5, 6, 9, 10, 15];
    var r = arr.filter(function (x) {
        return x % 2 === 0;
    r; // [1, 5, 9, 15]

Callback function

The callback function received by filter() can actually have multiple parameters. Usually, we only use the first parameter to represent an element of the Array. The callback function can also receive two other parameters, indicating the position of the element and the Array itself:

var arr = ['A', 'B', 'C'];
var r = arr.filter(function (element, index, self) {
    console.log(element); // Print 'A', 'B', 'C' in sequence
    console.log(index); // Print 0, 1, 2 in sequence
    console.log(self); // self is the variable arr
    return true;

Using filter, you can skillfully remove the duplicate elements of Array:

var arr = ['apple', 'strawberry', 'banana', 'pear', 'apple', 'orange', 'orange', 'strawberry'];
var r = arr.filter(function (element, index, self) {
    return self.indexOf(element) === index;

Removing duplicate elements depends on indexOf always returning the position of the first element. The position of subsequent duplicate elements is not equal to that returned by indexOf, so it is filtered out by the filter.


The sort() method of JavaScript Array is used for sorting, but the sorting results may surprise you:

// Normal looking results:
['Google', 'Apple', 'Microsoft'].sort(); // ['Apple', 'Google', 'Microsoft'];

// apple came last:
['Google', 'apple', 'Microsoft'].sort(); // ['Google', 'Microsoft", 'apple']

// Unintelligible results:
[10, 20, 1, 2].sort(); // [1, 10, 2, 20]

The second sort puts apple last because strings are sorted according to ASCII code, while the ASCII code of lowercase letter a comes after the uppercase letter.

What's the third ranking result? Can simple numerical sorting be wrong?

This is because the Array's sort() method converts all elements to String by default, and then sorts. The result '10' is ahead of '2', because the character '1' is smaller than the ASCII code of the character '2'.

If you don't know the default sort rule of sort() method, sort the numbers directly and fall into the pit!

Fortunately, the sort() method is also a high-order function, which can also receive a comparison function to implement custom sorting.

To sort by number size, we can write:

'use strict';

var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
    if (x < y) {
        return -1;
    if (x > y) {
        return 1;
    return 0;
console.log(arr); // [1, 2, 10, 20]

// Reverse order
var arr = [10, 20, 1, 2];
arr.sort(function (x, y) {
    if (x < y) {
        return 1;
    if (x > y) {
        return -1;
    return 0;
}); // [20, 10, 2, 1]

//number type sort rewrite
console.log(arr.sort((x, y) => x - y)); // [1, 2, 10, 20]

Finally, the sort() method will directly modify the Array, and the result it returns is still the current Array:

var a1 = ['B', 'A', 'C'];
var a2 = a1.sort();
a1; // ['A', 'B', 'C']
a2; // ['A', 'B', 'C']
a1 === a2; // true, a1 and a2 are the same object

For arrays, in addition to map(), reduce, filter(), sort(), these methods can pass in a function, the Array object also provides many very practical high-order functions.


The every() method can determine whether all elements of the array meet the test conditions.

var arr = ['Apple', 'pear', 'orange'];
console.log(arr.every(function (s) {
    return s.length > 0;
})); // true, because each element satisfies s.length > 0

console.log(arr.every(function (s) {
    return s.toLowerCase() === s;
})); // false, because not every element is lowercase


The find() method is used to find the first element that meets the conditions. If it is found, it returns this element. Otherwise, it returns undefined:

var arr = ['Apple', 'pear', 'orange'];
console.log(arr.find(function (s) {
    return s.toLowerCase() === s;
})); // 'pear', because pear is all lowercase

console.log(arr.find(function (s) {
    return s.toUpperCase() === s;
})); // undefined because there are no elements that are all uppercase


findIndex() is similar to find(). It is also the first element that meets the criteria. The difference is that findIndex() will return the index of this element. If it is not found, it will return - 1:

var arr = ['Apple', 'pear', 'orange'];
console.log(arr.findIndex(function (s) {
    return s.toLowerCase() === s;
})); // 1, because the index of 'pear' is 1

console.log(arr.findIndex(function (s) {
    return s.toUpperCase() === s;
})); // -1


Like map(), foreach () applies each element to the incoming function in turn, but does not return a new array. forEach() is often used to traverse arrays, so the passed in function does not need to return a value:

var arr = ['Apple', 'pear', 'orange'];
arr.forEach(console.log); // Print each element in turn


  • The difference between findIndex and indexOf in JavaScript

    • The first parameter of indexOf, expect a value, can be used for arrays of primitive type

      What is thrown in is the element to be found. Find the element directly.

    • A parameter of findIndex, expect a callback, can be used for arrays of complex data types or when the search condition is more complex than a value

      What is thrown in is a function. Find the elements that meet the functional relationship.

Function supplement


apply()Package parameters into Array Re afferent;
call()Pass the parameters in order.

Math.max.apply(null, [3, 5, 4]); // 5, 3, 5, 4); // 5

With apply(), we can also dynamically change the behavior of functions.

var count = 0;
var oldParseInt = parseInt; // Save original function

window.parseInt = function () {
    count += 1;
    return oldParseInt.apply(null, arguments); // Call original function

// Test:
console.log('count = ' + count); // 3

Analog call implementation


Add method fn to object object to run object fn, this points to the object, thus changing the direction of this

Get function parameters through arguments

var a = 100
let object = {
  a: 1,
  b: 2
function foo (n1, n2) {
Function.prototype.call1 = function (o) {
  let object = o || window
  object.fn = this
  // Get parameters
  let params = []
  for (let i = 1; i < arguments.length; i++) {
    // params.push('arguments[' + i + ']')
  // Run function
  // eval('object.fn(' + params +')')
foo.call1(object,'lisi', 'zhangsan')


JavaScript also has a free keyword arguments, which only works inside the function and always points to all parameters passed in by the caller of the current function. Arguments is similar to Array, but it is not an Array:

function foo(x) {
    console.log('x = ' + x); // 10
    for (var i=0; i<arguments.length; i++) {
        console.log('arg ' + i + ' = ' + arguments[i]); // 10, 20, 30
foo(10, 20, 30);

arguments can get all the parameters passed in by the caller

callee caller

rest parameter ES6

function foo(a, b, {
    console.log('a = ' + a);
    console.log('b = ' + b);

foo(1, 2, 3, 4, 5);
// result:
// a = 1
// b = 2
// Array [ 3, 4, 5 ]

// result:
// a = 1
// b = undefined
// Array []

The rest parameter can only be written at the end. Use From the running results, we can see that the incoming parameters are bound to a and b first, and the redundant parameters are given to the variable rest in the form of array. Therefore, we no longer need arguments, so we get all the parameters.

Variable promotion

The function definition of JavaScript has a feature. It will scan the statements of the whole function body first and "promote" all declared variables to the top of the function:

function foo() {
    var x = 'Hello, ' + y;
    var y = 'Bob';


// After lifting
function foo() {
    var y; // Promote the declaration of variable y, where y is undefined
    var x = 'Hello, ' + y;
    y = 'Bob';


Global variables are bound to window s. If different JavaScript files use the same global variables or define top-level functions with the same name, they will cause naming conflicts and are difficult to find.

One way to reduce conflicts is to bind all your variables and functions to a global variable. For example:

// Unique global variable MYAPP:
var MYAPP = {};

// Other variables: = 'myapp';
MYAPP.version = 1.0;

// Other functions: = function () {
    return 'foo';

This is how jQuery is implemented

Deconstruction assignment ES6

var [x, y, z] = ['hello', 'JavaScript', 'ES6'];
// x. Y and Z are respectively assigned as the corresponding elements of the array:
console.log('x = ' + x + ', y = ' + y + ', z = ' + z);

Deconstruction assignment can ignore some elements

let [, , z] = ['hello', 'JavaScript', 'ES6']; // The first two elements are ignored and only the third element is assigned to z
z; // 'ES6'

Object deconstruction assignment can quickly obtain the attributes specified by the object

var person = {
    name: 'Xiao Ming',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school'
var {name, school,age, passport} = person;
// Name, age and passport are assigned as corresponding attributes respectively:
console.log('name = ' + name + ', age = ' + age + ', passport = ' + passport+ ',school='+ school);

You can assign values to nested object attributes to ensure that the corresponding levels are consistent:

var person = {
    name: 'Xiao Ming',
    age: 20,
    gender: 'male',
    passport: 'G-12345678',
    school: 'No.4 middle school',
    address: {
        city: 'Beijing',
        street: 'No.1 Road',
        zipcode: '100001'
var {name, address: {city, zip}} = person;
name; // 'Xiao Ming'
city; // 'Beijing'
zip; // undefined because the attribute name is zipcode instead of zip
// Note: address is not a variable, but to let city and zip obtain the properties of nested address objects:
address; // Uncaught ReferenceError: address is not defined

Deconstruction assignment can also use the default value to avoid returning undefined if there is no attribute

var person = {
    name: 'Xiao Ming',
    age: 20,
    gender: 'male',
    passport: 'G-12345678'

// If the person object does not have a single attribute, the default value is true:
var {name, single=true} = person;
name; // 'Xiao Ming'
single; // true

If a function takes an object as a parameter, you can use deconstruction to bind the object's properties directly to variables. For example, the following function can quickly create a Date object:

function buildDate({year, month, day, hour=0, minute=0, second=0}) {
    return new Date(year + '-' + month + '-' + day + ' ' + hour + ':' + minute + ':' + second);

Its convenience is that the passed in object only needs three attributes: year, month and day:

buildDate({ year: 2017, month: 1, day: 1 });
// Sun Jan 01 2017 00:00:00 GMT+0800 (CST)

You can also pass in the hour, minute, and second attributes:

buildDate({ year: 2017, month: 1, day: 1, hour: 20, minute: 15 });
// Sun Jan 01 2017 20:15:00 GMT+0800 (CST)

Arrow function ES6

A new function in ES6

x => x*x
 Equivalent to
function (x) {
	return x*x;

The arrow function is equivalent to an anonymous function and simplifies the function definition. The arrow function has two formats. One, like the one above, contains only one expression, even {...} And return are omitted. Another method can contain multiple statements. In this case, {...} And return:

x => {
    if (x > 0) {
        return x * x;
    else {
        return - x * x;

If the parameter is not one, it needs to be enclosed in parentheses ():

/ Two parameters:
(x, y) => x * x + y * y

// No parameters:
() => 3.14

// Variable parameters:
(x, y, => {
    var i, sum = x + y;
    for (i=0; i<rest.length; i++) {
        sum += rest[i];
    return sum;


Arrow function seems to be a shorthand for anonymous function, but in fact, there is an obvious difference between arrow function and anonymous function: this in arrow function is lexical scope, which is determined by context.

Recalling the previous example, due to the error handling of this binding by JavaScript function, the following example can not get the expected results:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = function () {
            return new Date().getFullYear() - this.birth; // this points to window or undefined
        return fn();

Now, the arrow function completely fixes the pointing of this. This always points to the lexical scope, that is, the outer caller obj:

var obj = {
    birth: 1990,
    getAge: function () {
        var b = this.birth; // 1990
        var fn = () => new Date().getFullYear() - this.birth; // this points to the obj object
        return fn();
obj.getAge(); // 25

If the arrow function is used, the previous hack method:

var that = this; 

You don't need it anymore

Since this has been bound according to the lexical scope in the arrow function, this cannot be bound when calling the arrow function with call() or apply(), that is, the first parameter passed in is ignored:

var obj = {
    birth: 1990,
    getAge: function (year) {
        var b = this.birth; // 1990
        var fn = (y) => y - this.birth; // this.birth is still 1990
        return{birth:2000}, year);
obj.getAge(2015); // 25

generator ES generator

The generator here is similar to that of python

unction foo(x) {
    return x + x;

var r = foo(1); // Call foo function

During the execution of the function, if no return statement is encountered (if there is no return at the end of the function, it is an implicit return undefined;), Control cannot be returned to the called code.

generator is very similar to a function and is defined as follows:

function* foo(x) {
    yield x + 1;
    yield x + 2;
    return x + 3;

The difference between the generator and the function is that the generator is defined by function * (note the extra * sign), and in addition to the return statement, it can also be returned multiple times with yield.

function* fib(max) {
        a = 0,
        b = 1,
        n = 0;
    while (n < max) {
        yield a;
        [a, b] = [b, a + b];
        n ++;

fib(5); // fib {[[GeneratorStatus]]: "suspended", [[GeneratorReceiver]]: Window}

Calling a generator directly is different from calling a function. fib(5) just creates a generator object and hasn't executed it yet

There are two methods to call the generator object. One is to continuously call the next() method of the generator object:

var f = fib(5);; // {value: 0, done: false}; // {value: 1, done: false}; // {value: 1, done: false}; // {value: 2, done: false}; // {value: 3, done: false}; // {value: undefined, done: true}

The next() method will execute the code of the generator, and then every time it encounters yield x; Return an object {value: x, done: true/false}, and then "pause". The returned value is the return value of yield, and done indicates whether the generator has finished executing. If done is true, then value is the return value of return.

When done is true, the generator object has been completely executed. Do not call next().

The second method is to use for Of loop iterates over the generator object. We don't need to judge ourselves in this way. done:

function* fib(max) {
        a = 0,
        b = 1,
        n = 0;
    while (n < max) {
        yield a;
        [a, b] = [b, a + b];
        n ++;

for (var x of fib(10)) {
    console.log(x); // Output 0, 1, 1, 2, 3

What is the use of generator compared with ordinary functions?

Because the generator can return multiple times during execution, it looks like a function that can remember the execution state. Using this, writing a generator can realize the functions that can be realized only by object-oriented. For example, if you use an object to save state, you have to write it this way

var fib = {
    a: 0,
    b: 1,
    n: 0,
    max: 5,
    next: function () {
            r = this.a,
            t = this.a + this.b;
        this.a = this.b;
        this.b = t;
        if (this.n < this.max) {
            this.n ++;
            return r;
        } else {
            return undefined;

It is quite cumbersome to save the state with the properties of the object.

Another great benefit of generator is to turn asynchronous callback code into "synchronous" code. This benefit can only be realized after learning AJAX later.

In the dark ages before generator, you need to write code like this when using AJAX:

ajax('http://url-1', data1, function (err, result) {
    if (err) {
        return handle(err);
    ajax('http://url-2', data2, function (err, result) {
        if (err) {
            return handle(err);
        ajax('http://url-3', data3, function (err, result) {
            if (err) {
                return handle(err);
            return success(result);

The more callbacks, the uglier the code.

With the wonderful era of generator, you can write this when using AJAX:

try {
    r1 = yield ajax('http://url-1', data1);
    r2 = yield ajax('http://url-2', data2);
    r3 = yield ajax('http://url-3', data3);
catch (err) {


Closures are created whenever variables defined outside the current scope are accessed within an internal scope. It allows you to access the scope of external functions from internal functions. In JS, closures are created every time a function is created. To use closures, simply define a function within another function and expose it.

Closure: a function that has access to a variable in the scope of another function.

Function as return value

In addition to accepting functions as parameters, higher-order functions can also return functions as result values.

Let's implement a sum of arrays. Generally, the summation function is defined as follows:

function sum(arr) {
    return arr.reduce(function (x, y) {
        return x + y;

sum([1, 2, 3, 4, 5]); // 15

However, what if we don't need to sum immediately, but recalculate as needed in the later code? You can return the summation function instead of the summation result!

function lazy_sum(arr) {
    var sum = function () {
        return arr.reduce(function (x, y) {
            return x + y;
    return sum;

When we call lazy_sum() does not return the summation result, but the summation function:

var f = lazy_sum([1, 2, 3, 4, 5]); // function sum()

When function f is called, the summation result is really calculated:

f(); // 15

In this example, we are in the function lazy_ The function sum is defined in sum, and the internal function sum can refer to the external function lazy_sum parameters and local variables, when lazy_ When sum returns the function sum, the relevant parameters and variables are saved in the returned function. This program structure called "Closure" has great power.

Notice again that when we call lazy_ When sum(), each call will return a new function, even if the same parameters are passed in:

var f1 = lazy_sum([1, 2, 3, 4, 5]);
var f2 = lazy_sum([1, 2, 3, 4, 5]);
f1 === f2; // false

The call results of f1() and f2() do not affect each other.


Note that the returned function references the local variable arr inside its definition. Therefore, when a function returns a function, its internal local variable is also referenced by the new function. Therefore, closures are simple to use and not easy to implement.

Another problem to note is that the returned function is not executed immediately, but not until f() is called. Let's take an example:

function count() {
    var arr = [];
    for (var i=1; i<=3; i++) { // Just use let
        arr.push(function () {
            return i * i;
    return arr;

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

In the above example, a new function is created for each loop, and then the three created functions are added to an Array to return.

You may think that calling f1(), f2() and f3() should result in 1, 4 and 9, but the actual result is:

f1(); // 16
f2(); // 16
f3(); // 16

All 16! The reason is that the returned function references the variable i, but it does not execute immediately. When all three functions return, the variable i they refer to has become 4, so the final result is 16.

One thing to keep in mind when returning closures is that the return function should not reference any cyclic variables or variables that will change later.

What if you have to reference a loop variable? The method is to create another function and bind the current value of the loop variable with the parameter of the function. No matter how the loop variable changes later, the value bound to the function parameter remains unchanged:

function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push((function (n) {
            return function () {
                return n * n;
    return arr;

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

f1(); // 1
f2(); // 4
f3(); // 9

Note that a syntax of "create an anonymous function and execute it immediately" is used here:

(function (x) {
    return x * x;
})(3); // 9

In theory, create an anonymous function and execute it immediately. It can be written as follows:

function (x) { return x * x } (3);

However, due to the problem of JavaScript syntax parsing, SyntaxError will be reported. Therefore, the whole function definition needs to be enclosed in parentheses:

(function (x) { return x * x }) (3);

Generally, an anonymous function that executes immediately can disassemble the function body, which is generally written as follows:

(function (x) {
    return x * x;

After all, is closure to return a function and delay execution?

Of course not! Closures are very powerful. For example, chestnuts:

In object-oriented programming languages, such as Java and C + +, to encapsulate a private variable inside an object, you can modify a member variable with private.

In a language with no class mechanism and only functions, you can also encapsulate a private variable with the help of closures. We create a counter with JavaScript:

'use strict';

function create_counter(initial) {
    var x = initial || 0;
    return {
        inc: function () {
            x += 1;
            return x;

It works like this:

var c1 = create_counter();; // 1; // 2; // 3

var c2 = create_counter(10);; // 11; // 12; // 13

In the returned object, a closure is implemented, which carries the local variable x, and the variable x cannot be accessed from external code at all. In other words, a closure is a function that carries a state, and its state can be completely hidden.

Closures can also turn multi parameter functions into single parameter functions. For example, to calculate xy, you can use math Pow (x, y) function. However, considering that x2 or x3 are often calculated, we can use closures to create new functions pow2 and pow3:

'use strict';

function make_pow(n) {
    return function (x) {
        return Math.pow(x, n);
// Create two new functions:
var pow2 = make_pow(2);
var pow3 = make_pow(3);

console.log(pow2(5)); // 25
console.log(pow3(7)); // 343

Disadvantages of closures: memory leaks require manual memory release

Function throttling and function anti chattering

js basic knowledge supplement

  • isNaN(NaN) to determine whether the type is NaN

  • Floating point numbers will produce errors in the operation process, because the computer cannot accurately represent infinite circular decimals. To compare whether two floating-point numbers are equal, you can only calculate the absolute value of their difference to see if it is less than a threshold:

    Math.abs(1 / 3 - (1 - 2 / 3)) < 0.0000001; // true
  • null and undefined

  • Strings \: escape characters

  • Use backquotes for multiline strings`

  • Template string

    var name = 'Xiao Ming';
    var age = 20;
    console.log(`Hello, ${name}, You this year ${age}Years old!`);
  • String operation s = "Hello,world!"

    • Accessing the character s[0] at a specified position of the query string is immutable. It is useless to modify the string through s[0] = 1
    • toUpperCase
    • toLowerCase
    • indexOf
    • substring
    • split
  • array

    • indexOf

    • slice

    • push

    • pop

    • unshift

    • shift

    • Sort sort pit

    • Reverse reverse

    • A universal method of modifying arrays by splice

      var arr = ['Microsoft', 'Apple', 'Yahoo', 'AOL', 'Excite', 'Oracle'];
      // Delete three elements from index 2, and then add two more elements:
      arr.splice(2, 3, 'Google', 'Facebook'); // Return deleted elements ['yahoo ',' AOL ',' excite ']
      arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
      // Delete only, do not add:
      arr.splice(2, 2); // ['Google', 'Facebook']
      arr; // ['Microsoft', 'Apple', 'Oracle']
      // Add only, not delete:
      arr.splice(2, 0, 'Google', 'Facebook'); // Returned [], because no element was deleted
      arr; // ['Microsoft', 'Apple', 'Google', 'Facebook', 'Oracle']
    • concat connects two arrays and puts back a new array without modifying the original array

    • join connects with the specified string

  • object

    • To determine whether a property is owned by xiaoming rather than inherited, you can use the hasOwnProperty() method:

      var xiaoming = {
          name: 'Xiao Ming'
      xiaoming.hasOwnProperty('name'); // true
      xiaoming.hasOwnProperty('toString'); // false
  • Map and Set ES6
    A small problem with JavaScript objects is that the key must be a string. But in fact, Number or other data types are also very reasonable as keys.

    • Map is the structure of a group of key value pairs, which has extremely fast search speed.

      var m = new Map(); // Empty Map
      m.set('Adam', 67); // Add new key value
      m.set('Bob', 59);
      m.has('Adam'); // Whether key 'Adam' exists: true
      m.get('Adam'); // 67
      m.delete('Adam'); // Delete key 'Adam'
      m.get('Adam'); // undefined
    • set

      var s = new Set([1, 2, 3, 3, '3']);
      s; // Set {1, 2, 3, "3"}

      You can add elements to the Set by using the add(key) method. You can add elements repeatedly, but it will not have any effect:

      Elements can be deleted through the delete(key) method:

  • iterable ES6

    ES6 standard introduces a new iterable type. Array, Map and Set all belong to iterable type.

    • Collections with iterable types can be accessed through the new for Of loop.

    • for... in takes the key

      var a = ['A', 'B', 'C']; = 'Hello';
      for (var x in a) {
          console.log(x); // '0', '1', '2', 'name'
    • for... of traverses itself

    • foreach

      var s = new Set(['A', 'B', 'C']);
      s.forEach(function (element, sameElement, set) {

js method to listen for attributes in an object

Use the method definePrpperty in the constructor
obj = {}
console.log('attribute changed ')
}) = 'value' / / execute the set method to listen for attributes

todo read vue source code diff patch

diff algorithm

Data binding

[the external chain picture transfer fails. The source station may have an anti-theft chain mechanism. It is recommended to save the picture and upload it directly (img-n0IOnAgJ-1641822732986)(image/bVBQYu)]

Keywords: Javascript Front-end Interview

Added by evilgenius on Tue, 11 Jan 2022 13:05:17 +0200