Universal JS (ten thousand words, foundation, principle, interview, continuous update...)

Universal JS

JS (JavaScript lightweight dynamic scripting language)

JavaScript is a dynamic scripting language based on prototype programming and multi paradigm, and supports object-oriented, imperative, declarative and functional programming paradigms

  • ECMAScript: syntax specification, which should be followed by js and nodejs
  • js operation dom, event, send ajax request = = ECMAScript + webAPI
  • node processing request operation file = = ECMAScript + nodeAPI

Object oriented thinking:

  • 1. Encapsulation: protecting members, data hiding - methods, mandatory access rights, easy to understand
  • 2. Inheritance: reuse code, no need to modify parent class, * multiple inheritance (combination) -- JS does not support, bad, * abstract class
  • 3. Polymorphism: abstract and simplified problems (conditional judgment simulation polymorphism)

Scope

  • 1. Global scope

    • Global variables defined by var cannot be deleted. Global variables not defined by var are window attributes. They can be deleted abcd=123, delete ABCD = > true
    • There is no global variable defined by var in the function, and the attribute of window also exists
  • 2. Function scope

  • 3. Block scope let & const

    • let block level scope

    • let declared global variables cannot be accessed with global attributes. Variables will not be defined on the window

    • let cannot be redefined

    • let does not promote variables

    • const: constant, immutable quantity, pointer and content cannot be changed

    // let's block level acts on
    for (var i = 0; i < 3; i++) {
      setTimeout(function () {
        console.log(i);
      }, 1000);
    } // 3 let is 0 1 2
    
    // There is no pre explanation
    console.log(a);
    var a = 1; // undefined
    let a = 1; // Cannot access' a 'before initialization cannot access' a' before initialization
    
    // const is an immutable quantity. The pointer cannot be changed and the content cannot be changed
    const a = 1;
    a = 2; // Uncaught TypeError: Assignment to constant variable.
    const b = [1];
    b.push(2);
    console.log(b); // [1,2]
    Object.freeze(b); // =>It can't be changed at all
    b.push(3); // Uncaught TypeError: Cannot add property 3, object is not extensible
    
  • 4. Dynamic scope

The pre interpretation (variable tone) browser comes naturally

In the current scope, before js code is executed, the browser will declare or define all with var and function in advance by default

  • declare: var num; Tell the browser that there is a global variable in the global scope
  • defined: num=12; Assign values to variables and link data variables together
  • var and function

    • var variables are declared in advance but will not be assigned (undefined). The default value is undefined and will be assigned only when the code is executed.
    • function is declared and assigned in advance (definition)
      // Pre interpretation only occurs in the current scope. For example, pre interpretation only occurs in windows at the beginning, and pre interpretation only occurs in the function when the function is executed
      console.log(num); //undefined
      console.log(obj); //undefined
      console.log(sum); //function itself
      var num=12;       //assignment
      function sum(num1,num2){var total=num1+num2;}
      var obj={'name':'zqb',age:30};  //Object opens up a space for storing attribute names and attribute values
      *****************************
      console.log(haha);        // haha is not defined
      var a =function(){};      //It will not assign values in advance. The pre interpretation will only look at the variables to the left of the equal sign, not what your value is
      function (){             //When the code is executed, the declaration and assignment are finished. Skip directly
          function haha(){}    //Our pre interpretation occurs only in the current scope*************
      }
    
  • The difference between adding VaR and not adding var: (under the global scope)

    • Whether 1 is declared in advance (declaration in advance with VaR and no pre interpretation without var)
    • 2. Global variables defined by var cannot be deleted. Global variables not defined by var are window attributes. They can be deleted abcd=123, delete ABCD = > true
  • The operation sequence of the function: 1. If there are formal parameters, it is the formal parameter assignment. 2. Pre interpretation. 3. The code is executed line by line..

  • Pre interpretation mechanism

    • 1 whether the condition is true or not, it will be pre interpreted (if) only declared in chrome
    • 2. During pre interpretation, those with var keyword only look to the left of the equal sign
    • 3 self executing functions under the global scope will not be pre interpreted, and pre interpretation only occurs in the current scope
    • 4The code behind return will still be pre interpreted, but the value from return will not be pre interpreted. Even a function will not be pre interpreted. The code behind return will not be executed. The return value behind return will be pre interpreted but will not be executed
    • 5. When the variable names of var and function are the same, they cannot be declared repeatedly, but the assignment is repeated
    //Mechanism 1
    if ("num" in window) {
      //Declare num=undefined in advance
      var num = 6; //Assign value to num
    }
    console.log(num); //6
    
    //Mechanism 2
    var a = function () {};
    sum(); //Uncaught ReferenceErrer:sum is not defined
    
    //Mechanism 3
    console.log(b); //b is not defined
    !(function () {
      //Self executing functions are not pre interpreted
      var b = 0;
    })();
    
    //Mechanism 4
    function fn() {
      console.log(num); //undefined
      return function () {
        console.log(num);
      }; //The return value after return is not pre interpreted
      alert(); //Code not executed
      var num = 9; //This place is also pre interpreted and can never be defined, because the code can't go here
    }
    var f = fn(); //The execution assignment of a function is the result of execution. If there is no return, it is undefined
    fn();
    
    //Mechanism 5
    var sum = 10;
    function sum() {}
    sum(); //Cannot execute Uncaught TypeError: sum is not a function
    //Step 1: pre explain var sum =undefined; Sum = function body
    //Step 2: the real assignment var sum = 10
    
    foo(); //2 pre interpretation first assignment
    function foo() {
      console.log(1);
    }
    foo(); //2
    var foo = "haha"; //The original function reference address has been destroyed, and foo assigns a string to execute
    foo(); //foo is not a function
    function foo() {
      console.log(2); //It will also be assigned during pre interpretation
    }
    foo(); //The error report cannot be executed here
    

Classification of memory in JS

  • Stack memory: used to provide an environment - > scope (global scope / private scope) for JS code execution. Basic data types are stored in stack memory
  • Heap memory: used to store the value of the reference data type - > the object stores the attribute name and attribute value, and the function stores the code string

JS data type

  • Basic data types: String, Number, Boolean, Null, Undefined, symbol.

    Value type (not interfering with each other)

  • Reference data types: Object, Array, Function

    Reference type (address, mutual influence)

Test data type

  • typeof: advantages: it can quickly distinguish basic data types. Disadvantages: object, Array and Null cannot be distinguished, and object is returned

  • instanceof: advantages: it can distinguish Array, Object and Function, and is suitable for judging custom class instance objects. Disadvantages: Number, Boolean and String basic data types cannot be judged. Principle: judge whether the attribute of the instance Object and the attribute of the constructor refer to the same address

    console.log(2 instanceof Number); // false
    console.log([] instanceof Array); // true
    
  • Constructor constructor

  • Object.prototype.toString.call(): advantages: accurate judgment of data types. Disadvantages: cumbersome writing and difficult to remember. It is recommended to use after encapsulation

    var toString = Object.prototype.toString;
    console.log(toString.call(2)); //[object Number]
    

Type conversion

  • Forced type conversion: parseInt, parseFloat, toString
  • Implicit type conversion: if, logical operation, = =, +, concatenation string
  • Type conversion: String splicing, = =,!!
false=='' //true
null==undefined //true
obj.a==null amount to obj.a===null||obj.a===undefined
const a = 0
!a //true
!!a //false
!!0 === false //true
!!NaN === false //true
!!null ===false //true
!!undefined === false //true
10&&0 //0
abc||'' //abc
// Interview questions
var num = 20; //20 * = 3 = 60 execute fn() in 30 lines to change window.num *= 4l by 240
var obj = {
  num: 30, //120
  fn: (function (num) {
    //num = 20
    this.num *= 3; //this=>window.num*=3==60;
    num += 20; //20+=20 = 40;// The num variable in the current scope is changed to 40
    var num = 45; //Because it is the same as the formal parameter, it is not pre interpreted. Whether this var has the same effect as here num = 45;
    return function () {
      this.num *= 4; //When line 30 is executed, this is window, window.num *=4==240;
      num += 20; //num+=20 =65
      console.log(num); //65
    };
  })(this.num), //Who is this? Window = = > window.num
};
var fn = obj.fn; //Tell FN the reference address of obj.fn
fn(); //65
obj.fn(); // 85 this is obj, so this.num=30*4=120
console.log(window.num, obj.num); // 240 120

Difference between null and undefined

  • undefined usage:
    • When a variable is declared but not assigned, it is equal to undefined.
    • When calling the function, the parameter that should be provided is not provided, and the parameter is equal to undefined.
    • The object has no assigned property, and the value of the property is undefined.
    • When the function does not return a value, it returns undefined by default.
  • Null null pointer is used to represent an object that does not exist. It is often used to indicate that a function attempts to return a non-existent object. Usage:
    • 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.

The direction of this (the value is determined when the function is executed, not in the function)

  • 1. Object, click the event, and whoever calls this will point to who
  • 2. this in the constructor points to the current instance
  • 3. In the function, this points to window, and the strict mode is this = > undefined
  • 4. call, apply, bind can change the direction of this
    fn.call(thisObj,p1,p2) === fn.apply(thisObj,[p1,p2]);
  • 5. this of the arrow function takes the value of the parent scope

closure

  • In essence, it is to build a bridge inside and outside the function so that the child function can access all local variables in the parent function, but not vice versa. This is only one of the functions of closures. The other is to protect variables from external pollution and keep them in memory. We'd better use closures less in our work, Because closures consume too much memory, try not to use them when you have to.
//  Closures hide data: only API s are provided
function createCache() {
  const data = {}; //  The data in the closure is hidden and not accessed by the outside world
  return {
    set: function (key, val) {
      data[key] = val;
    },
    get: function (key) {
      return data[key];
    },
  };
}
const c = createCache();
c.set("a", 100);
console.log(c.get("a"));

// let block level scope is solved
let a;
for (let i = 0; i < 10; i++) {
  a = document.createElement("a");
  a.innerHTML = i + "<br>";
  a.addEventListener("click", function (e) {
    // If i is global, i has become 10 when clicking
    e.preventDefault();
    alert(i);
  });
  document.body.appendChild(a);
}

//Impact of closures: the occupied memory is not released, and the memory is released successively after the function is executed
let a = 0;
function fn1() {
  let a1 = 100;
  function fn2() {
    let a2 = 200;
    function fn3() {
      let a3 = 300;
      return a + a1 + a2 + a3;
    }
    fn3();
  }
  fn2();
}
fn1();

The difference between call,apply and bind

  • The function is to bind the function to the context to change the direction of this in the function; The difference lies in the grammar.
  • The difference between apply and call is that call accepts several parameters, the second parameter of apply is an array, and the bind() method creates a new function. When called, set its this keyword to the provided value. When calling a new function, provide a given parameter sequence before any provision.
sayName.call(callObj, "call param");
sayName.apply(applyObj, ["apply param"]);
let bindFn = sayName.bind(bindObj, "bind param");
bindFn();
  • call accepts several parameter lists. The first parameter of the method:

    • 1. If it is an object type, this inside the function points to the object
    • 2. If it is undefined or null, this inside the function points to window
    • 3. If it is a Number, this points to the instance of the corresponding Number constructor: 1 – > new Number (1); If it is a String, this points to the instance "abc" - > new String ("abc") of the String constructor; If it is a Boolean value, this points to the instance of Boolean constructor. False -- > new Boolean (false)
  • The apply parameter is passed to the array. There are differences between call and apply: the forms of parameters are different

    function toString(a, b, c) {
      console.log(a + " " + b + " " + c);
    }
    toString.call(null, 1, 3, 5); //"1 3 5"
    toString.apply(null, [1, 3, 5]); //"1 3 5"
    
  • bind does not execute immediately

var obj = {
  age: 18,
  run: function () {
    console.log(this); //this:obj
    var _that = this;
    setTimeout(function () {
      //this points to window
      console.log(this.age); // undefined
      console.log(_that.age); //18
    }, 50);
  },
};
obj.run();

//bind is only available in es5 (IE9 +)
var obj5 = {
  age: 18,
  run: function () {
    console.log(this); //this:obj5
    setTimeout(
      function () {
        console.log(this.age);
      }.bind(this),
      50
    ); //this:obj5
    //By executing the bind method, the anonymous function itself is not executed, but the value of this inside the function is changed to point to obj5
  },
};
obj5.run();

//Basic usage of bind
function speed() {
  console.log(this.seconds);
}
//After the bind method is executed, a new function is generated. The logic in the new function is the same as the original. The only difference is that this points to {seconds:100}
var speedBind = speed.bind({ seconds: 100 });
speedBind(); //100

(function eat() {
  console.log(this.seconds);
}.bind({ seconds: 360 })()); //360

//  Simulate bind
myBind = function () {
  const arr = Array.from(arguments); // Parameter to array
  // const args = Array.prototype.slice.call(arguments);
  const t = args.shift(); // Take out the first item this
  const self = this; // fn1 in fn1.bind(...)
  return function () {
    // Returns a function
    return self.apply(t, args);
    //return self.call(t, ...args)
  };
};

And = difference:

  • ==, when the value types on both sides are different, type conversion should be carried out first, and then comparison

  • ===, no type conversion is required. Different types must be different.

    ==Type conversion process:

    • If the types are different, perform type conversion
    • Judge whether the comparison is null or undefined. If so, return true
    • Judge whether the two types are string and number. If so, convert the string to number
    • Judge whether one of them is a boolean. If so, change the boolean to number and then judge
    • Judge whether one party is an object and the other party is a string, number or symbol. If so, change the object to the original type and then judge

    Classic interview question: [] = =! [] why true conversion steps:

    • ! Operator has the highest priority,! [] will be turned to false, so the expression becomes [] = = false
    • According to rule (4) above, if one party is a boolean, the Boolean is converted to number, so the expression becomes [] = = 0
    • According to rule (5) above, convert the array to the original type, call the toString() method of the array, and convert [] to an empty string. Therefore, the expression becomes: '= = 0
    • According to rule (3) above, the data types on both sides are string and number, and the empty string is converted to 0,
      Therefore, the expression becomes: 0 = = 0, the data types on both sides are the same, and 0 = = 0 is true

Deep and shallow copies

// Shallow copy
function simpleClone(obj) {
  var result = {};
  for (var i in obj) {
    result[i] = obj[i];
  }
  return result;
}
// Deep copy
function deepClone(obj = {}) {
  if (typeof obj !== "object" || obj == null) {
    return obj;
  } // obj is null, or it is not returned directly from the object array
  let result; //  Initialization return result
  obj instanceof Array ? (result = []) : (result = {});
  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      //  Ensure that the key is not an attribute of the prototype
      result[key] = deepClone(obj[key]); //  Recursive call!!!
    }
  }
  return result; //  Return results
}

Anti shake and throttling

  • Normal execution llllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllllll
  • Function anti shake             l        l           l
  • Function throttling L     l     l     l     l     l     l     l     l
  • Debounce, as the name suggests, prevents jitter to avoid mistaking an event for multiple times

    • Scenario: log in, send SMS and other buttons to prevent users from clicking too fast, resulting in multiple requests,
      When the browser window size is adjusted, the resize times are too frequent, resulting in too many calculations. At this time, it needs to be in place at one time
      Save the text editor in real time. Save it one second after there is no change operation
    • Anti shake reset in clearTimeout(timer)
    function debounce(f, wait) {
      let timer;
      return (...args) => {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
          f(...args);
        }, wait);
      };
    }
    function debounce(fn, delay) {
      let timer = null;
      return function () {
        if (timer) clearTimeout(timer);
        timer = setTimeout(() => {
          fn.apply(this, arguments);
        }, delay);
      };
    }
    
  • Throttle controls the flow of water. Control the frequency of events, such as once in 1s. It is similar to the rate limit controlled by the server and gateway.

    • Scenario: scroll event, calculating location information every second, etc
      The browser plays events and calculates progress information every second
      The input box searches and sends the request in real time, displays the drop-down list, and sends the request every second
    • Throttling focuses on locking timer=timeout
function throttle(f, wait) {
  let timer;
  return (...args) => {
    if (timer) {
      return;
    }
    timer = setTimeout(() => {
      f(...args);
      timer = null;
    }, wait);
  };
}
function throttle(fn, cycle) {
  let start = Date.now();
  let now;
  let timer;
  return function () {
    now = Date.now();
    clearTimeout(timer);
    if (now - start >= cycle) {
      fn.apply(this, arguments);
      start = now;
    } else {
      timer = setTimeout(() => {
        fn.apply(this, arguments);
      }, cycle);
    }
  };
}
  • Summary:
    • Anti shake: to prevent shaking, the event trigger will be reset per unit time to avoid multiple events triggered by accidental injury. The code implementation focuses on clearing clearTimeout. Anti shake can be compared to waiting for the elevator. As long as one person comes in, he needs to wait a little longer. The business scenario is to avoid repeated submission of multiple clicks of the login button.
    • Throttling: controls the flow. Events can only be triggered once per unit time, which is similar to the rate limit on the server side. Code implementation focuses on unlocking and locking timer=timeout; timer=null. Throttling can be compared to passing traffic lights. You can pass a batch every time you wait for a red light.

array

  • Array traversal method in ES5:

    • for loop: break directly jumps out of the loop; The code below continue is not executed, and the next loop is executed
    • forEach(),every(),some(),for(let index in obj){},filter(),fill()
    for (var i = 1; i <= 10; i++) {
      if (i == 6) continue;
      console.log(i);
    } // 1234578910
    
    // forEach does not support break and continue
    arr.forEach((item) => {
      console.log(item);
    });
    
    // every is executed only once without returning true.
    arr.every((item) => {
      console.log(item);
      return true;
    });
    
    // for in supports continue. The index is a string, the array is also an object, and the array can also have attributes
    for (let index in obj) {
      console.log(index, obj[index]);
    }
    
    // every(): a false is a false
    let arr = [12, 3, 4];
    console.log(
      arr.every((item) => {
        return item > 3;
      })
    ); //false
    
    // some(): one truth is one truth
    let arr = [12, 3, 4];
    console.log(
      arr.some((item) => {
        return item == 3;
      })
    ); //true
    
  • ES6

    • for of, Array.from(), flat(n) level n layers, Array.of(), find(), findIndex(), copyWithin(), includes(), reduce()

      //for of traverses any data structure
      for (let item of arr) {
        console.log(item);
      }
      
      //Class array conversion array:
      // es5:
      [].slice.call(document.querySelectorAll("img")); //nodeList calls the array method
      // es6:
      Array.from(arguments);
      Array.from({ length: 5 }, function () {
        return 1;
      });
      
      // Flat: flat array
      [1, [2, 3]].flat(2) //[1,2,3]
      [1, [2, 3, [4, 5]].flat(3) //[1,2,3,4,5]
      [1[2, 3, [4, 5[...]].flat(Infinity)//[1,2,3,4...n]
      // Implement flat
      function flat(arr) {
        const isDeep = arr.some((item) => item instanceof Array); // View array hierarchy
        if (!isDeep) {
          return arr; //It's already the first floor
        }
        const res = Array.prototype.concat.apply([], arr); //One layer array flattening
        return flat(res); // recursion
      }
      
      // duplicate removal:
      function unique(arr) {
        const res = [];
        arr.forEach((item) => {
          if (res.indexOf(item) < 0) {
            res.push(item);
          }
        });
        return res;
        //Use set to remove duplicates:
        //const set = new Set(arr)
        //return [...set]
      }
      
      //Generate new array
      let array = Array(5);
      let array = [];
      //es6:
      Array.of(1, 2, 3, 4, 5);
      let array = Array(5).fill(1); //Array.fill(value,start,end), which does not restrict all filling and replacement
      
      //es5 find an element
      arr.filter(function (item) {
        return item === 6;
      }); //[6] Did not return [], not efficient, look it up again
      //es6:
      arr.find(function (item) {
        return item === 6;
      }); // 6. Only the first value is found without undefined
      
      arr.findIndex(function(item){return item===6})
      
      arr.copyWithin(target[, start[, end]])
      // target 0 is the index of the base. Copy the sequence to this position. If it is negative, target will be calculated from the end. If target is greater than or equal to arr.length, no copy will occur. If the target is after start, the copied sequence will be modified to conform to arr.length.
      // start 0 is the index of the base and starts copying the starting position of the element. If it is negative, start will start from the end. If start is ignored, copyWithin will copy from 0.
      // end 0 is the index of the base. It starts to copy the end position of the element. copyWithin will be copied to this location, but the elements in the end location will not be included. If it is negative, end will start from the end. If end is ignored, the copyWithin method will be copied to the end of the array (the default is arr.length).
      [].copyWithin(target,start,end) // Replace the data at the specified position through its own data and return the changed array.
      [1, 2, 3, 4, 5].copyWithin(1, 0, 3) // [1, 1, 2, 3, 5]
      
      const array1 = [1, 2, 3];
      console.log(array1.includes(2)); // true
      
      // reduce
      arr.reduce(callback(accumulator, currentValue[, index[, array]])[, initialValue])
      // The accumulator accumulates the return value of the callback; It is the cumulative value returned the last time the callback was called
      // The element being processed in the currentValue array
      // Index the index of the current element being processed in the optional array
      // Array optional array to call reduce()
      // initialValue is optional as the value of the first parameter when the callback function is called for the first time. If no initial value is provided, the first element in the array is used. Calling reduce on an empty array without an initial value will report an error.
      var flattened = [[0, 1], [2, 3], [4, 5]].reduce(
        ( acc, cur ) => acc.concat(cur),
        []
      ); // flattened is [0, 1, 2, 3, 4, 5]
      

Methods commonly used in arrays

  • Part I: addition, deletion, modification and query

    methodfunctionparameterReturn valueOriginal array
    pushAdd at the endAdded itemArray length after additionchange
    popDelete last itemnothingDeleted itemschange
    unshiftAdd an item at the beginningAdded itemArray length after additionchange
    shiftDelete the first item of the arraynothingDeleted itemschange
    splice(n,m,x)Start with index n, include n, delete m elements, and replace the original with xn is the index, m is the number, and x is the new replacement contentDeleted itemschange
    slice(n,m)Find index m from index n without m (query replication)N starts with index n, m to index MQuery array itemsunchanged
    • Add push: ary. Splice (ary. Length, 0, x) at the end; ary[ary.length]=10;

    • Delete pop: ary. Splice (ary. Length-1) at the end; ary.length--;

    • Add unshift: splice(0,0,x) at the beginning

    • Delete shift: splice at the beginning (0,1)

    • ary.splice(n); Start with index n and delete to the end of the array

    • ary.splice(0); Empty the array and return a newly cloned array

    • ary.splice(); If none of the items are deleted, an empty array is returned

    • splice(n,m,x): delete first and then replace with X. delete m elements from index n and replace the original with X. return the deleted content array. The original array is changed

    • splice (n, 0, x) adds new content, deletes 0 content from index n, and puts the newly added content in front of index n. The returned result is an empty array, and the original array is changed

    • slice(n,m) starts from index n, finds the place with index m, does not contain m, returns a new array, and the original array remains unchanged

    • slice(n) starts from the index n and finds the end of the array. N is a negative number, copied from right to left, M is a negative number, and m are subtracted from right to left

    • slice(0) / slice() clones the original array and returns a new array without modifying the original array

      let arr = [1, 2, 3, 4, 5, 6];
      console.log(arr.slice(-5, -2)); //[2,3,4]
      
  • The second part: array interception and splicing

    methodfunctionparameterReturn valueOriginal array
    concatSplice arrayArray to spliceSpliced arrayunchanged
    joinSplice arrayArray to spliceSpliced arrayunchanged
    toStringArray conversion stringnothingConverted Stringunchanged
    ary1.concat(ary2); // Splice ary2 and ary1, and ary2 is in the back
    // It's equivalent to cloning ary1
    ary1.concat();
    ary1.concat([]);
    
    //Extension: in eval: js, the method of changing a string into an expression execution
    var ary = [1, 2, 3, 4, 5, 6];
    console.log(eval(ary.join("+"))); //21
    
  • The third category: sorting

    methodfunctionparameterReturn valueOriginal array
    reverseInverted arraynothingInverted arraychange
    sortSort by certain rulesfunctionSortedchange
    ary.sort(); // In this way, only numbers within 10 can be sorted, because they are sorted according to UNICODE encoded values
    ary.sort((a, b) => a - b); // From small to large
    ary.sort((a, b) => b - a); // From large to small
    
  • The fourth category is ie678 incompatible

    • indexOf / lastIndexOf (the two methods of string are compatible with all browsers, but the array is incompatible). If the index of the first / last occurrence position in the array does not return - 1, the index value is returned. The original array remains unchanged

    • forEach / map is used to traverse each item in the array. The return value of forEach is undefined, and map returns a new array

      // The syntax of map is the same as that of forEach. The return value of forEach is undefined, and map returns a new array
      /*@params arr	Optional. The array object to which the current element belongs. thisArg 	 Optional. If the thisarg parameter has a value, this will point to the thisarg parameter every time the callback function is called. If this parameter is empty, "undefined" is passed to the "this" value*/
      array.forEach(function(currentValue, index, arr), thisArg)
      arr.map(function callback(currentValue, index, array) {
      // Return element for new_array
      }, thisArg)
      
      ary.forEach(function (item, index) {});
      // The original array remains unchanged, and the new array returned is that each item is multiplied by 10
      ary.map(function (item, index) {
        return item * 10;
      });
      console.log(ary);
      

Math method

  • Math.abs(); // absolute value
  • Math.pow(2,3); // Square 2 base 3 exponential magnifying glass
  • Math.sqrt(); // Open square magnifying glass
  • Math.ceil(); // Up the whole
  • Math.floor(); // Round down
  • Math.round(); // Rounding negative numbers requires special memory to move closer to the floor
  • Math.max(); // The maximum value is a set of numbers, not an array
  • Math.min(); // Take the minimum value
  • Math.random(); // Get random number from 0 to 1 [0,1]
  • Math.round(Math.random()*(m-n)+n); / / get the random integer from n to m (large small)

String string method

  • charAt obtains characters through the specified index value. The parameter is the index value, and the return value is the obtained characters (verification code)
  • charCodeAt gets the ASCII code value of the specified character through the index value
  • substr(n,m) interception: m are intercepted from index n, only one parameter is intercepted to the end by default, and the string remains unchanged
  • Substring (n, m) copy: copy index n to index m, excluding m, and only one parameter is intercepted to the end
  • Slice is the same as substring, except that slice supports negative index,
  • toUpperCase to uppercase
  • To lowercase to lowercase
  • The indexOf character appears at the index position in the string. If the corresponding index is returned, no - 1 is returned
  • lastIndexOf is incompatible with indexOf, the index array of the last occurrence position, and the string method is compatible
  • split splits the string into an array according to the specified separator
  • localCompare; String and string comparison, convert the two strings into pinyin, compare the alphabetical order, and the value is - 1,1,0
  • Replace (replaced, with whom) the replacement string can be followed by the function to replace only once, / a/g global matching
    let str = 'dfgfgdfg'; console.log(str.replace(/df/g, '666')); //666gfg666g
  • match -- when regular
  • endsWith() ends with xxx
  • startsWith() starts with xxx
  • includes() contains xxx
  • concat string splicing
  • padEnd()/padStart() fills in the string and fills in the blanks
  • trim()
  • trimEnd()
  • trimStart()
  • concat string splicing
    let greetList = ["Hello", " ", "Venkat", "!"];
    "".concat(...greetList); // "Hello Venkat!"
    

Date typeof date -- > "function"

Date time: new Date(); Parameters: objects converted to a time format

console.log(new Date()); //2020-04-29T06:39:49.605Z
console.log(date.getFullYear()); //year
console.log(date.getYear()); //It began in 1900
console.log(date1.getMonth()); //The month is 1 [0,11] smaller than the actual month
console.log(date.getDate()); //Date 1-31
console.log(date.getDay()); // [1,2,3,4,5,6,0] Sunday is 0
console.log(date.getHours()); //hour
console.log(date.getMinutes()); //branch
console.log(date.getSeconds()); //second
console.log(date.getMilliseconds()); //ms MS
console.log(date.getTime()); //This time object is 0:00:00:00 on January 1, 1970
  • ES9 For await of: asynchronous collection traversal

Class

// ES5:
let Animal = function (type) {
  this.type = type; //Private property
  this.eat = function () {}; //Private method
};
Animal.prototype.eat = function () {}; //Common method, prototype, chain integration
Animal.walk = function () {}; //Static method of es5 class
let dog = new Animal("dog");
dog.constructor.prototype.eat = function () {}; //Modify the prototype method of the class

// ES6:
class Animal {
  constructor(type) {
    //Write properties in the constructor and write methods outside the constructor
    this.type = type;
  }
  eat() {} //Public method, method on Prototype
  // es6 attribute protection
  get age() {
    return _age;
  } //Setting the age attribute dog.age is an entry
  set age(val) {
    if (val > 4) {
      // Intercept through set
      _age = val;
    }
  }
  static walk() {} //Static method: unable to get the instance object of the class
}
dog.age = 3; // 4 blocked by set and not effective

// Class instance method: on the prototype or this.eat private method

// es6 define private methods
class Widget {
  foo(name) {
    setName.call(this, name);
  }
}
function setName(name) {
  return (this.name = name);
}

Prototype chain

  • Class: prototype display prototype
  • Example: proto implicit prototype
  • 1 when creating constructor / class

    • Born with a prototype attribute.
    • The value of prototype is an object type (installed as our public attribute) console.log (person. Prototype)// Person {}
    • The value of prototype also has an inherent attribute called constructor constructor, and the value of this attribute is the function (constructor, class) itself console.log (person. Prototype. Constructor)// [Function: Person]
    //All objects are instances of Object (Object is called our base class)
    console.log(Person.prototype.__proto__); //{}
    console.log(Person.prototype.__proto__ == Object.prototype); //True object is also a function
    

    Constructor, class - > prototype (value: object type) - > constructor (value: constructor, class) itself

  • 2. Each instance is an object with proto attribute, which is the prototype of the class to which the instance belongs. Console. Dir (person. _ proto_ = = person. Prototype)// true

    Instance. proto - > class. prototype

  • 3 each reference type has its own proto attribute, so the value of prototype also has its own proto attribute. And the value of this attribute is also an Object type, up to our base class Object

    Instance. proto - > class. prototype.proto - > object.prototype

  • 4. The attributes and methods added through the class prototype are public, and each instance will bring its own

  • 5 when an instance method is running, if the method is private, it can be used directly. If it is not private, it can be used to find the prototype of the class through the proto. If not, it can be used to find the Object of the base class through the proto of the prototype. If there is no error, it can be used directly. We call this mechanism of proto search prototype chain.

    • Instance. proto = = = prototype
    • Prototype. Constructor = = = constructor
    • Constructor. Prototype = = = prototype
    • Instance. Constructor = = = constructor
var A = function () {};
var a = new A();
console.log(a.__proto__); //A {} (that is, the prototype object of constructor function A)
console.log(a.__proto__.constructor); //[Function: A] ` (function A itself)
console.log(a.__proto__.__proto__); //Object {} (that is, the prototype object of constructor function Object)
console.log(a.__proto__.__proto__.__proto__); //null
//Hasownproperty isprototypeof propertyisenumerable on Object

class jQuery {
  constructor(selector) {
    const result = document.querySelectorAll(selector);
    const length = result.length;
    for (let i = 0; i < length; i++) {
      this[i] = result[i];
    }
    this.length = length;
    this.selector = selector;
  }
  get(index) {
    return this[index];
  }
  each(fn) {
    for (let i = 0; i < this.length; i++) {
      const elem = this[i];
      fn(elem);
    }
  }
  on(type, fn) {
    return this.each((elem) => {
      elem.addEventListener(type, fn, false);
    });
  } // Extend many DOM API s
}

// plug-in unit
jQuery.prototype.dialog = function (info) {
  alert(info);
};

// "Making wheels"
class myJQuery extends jQuery {
  constructor(selector) {
    super(selector);
  } // Expand your own methods
  addClass(className) {}
  style(data) {}
}

Execution process of new

let newMethod = function (Parent, ...rest) {
  // 1. Create a new object based on the prototype attribute of the constructor;
  let child = Object.create(Parent.prototype);
  // 2. Pass this and call parameters to the constructor for execution
  let result = Parent.apply(child, rest);
  // 3. If the constructor does not return the object manually, it returns the object of the first step
  return typeof result === "object" ? result : child;
};

Difference between function declaration and function expression:

  • Function declaration function fn() {} / / the code will be preloaded before execution
  • Function expression const fn = function() {} / / will not be preloaded

Differences between new Object() and Object.create():

  • {} is equivalent to new Object(), prototype Object.prototype
  • Object.create(null) has no prototype Object.create({...}) can specify a prototype
const obj2 = new Object(obj1); // obj1===obj2 true all equal
const obj2 = Object.create(obj1); // obj1===obj2 false will put all obj1 methods on the prototype of obj2

inherit

let Dog = function () {
  Animal.call(this, "dog"); // Initialize the constructor of the parent class and pass parameters to get the private method of the parent
  // A.apply(this, arguments);
  this.run = function () {}; //Private methods of subclasses
};
Dog.prototype = Animal.prototype; //Reference the same memory address

class Dog extends Animal {
  construtor(type) {
    //Show implicit
    super(type); // Like the constructor parameter of the parent class, super should be written on this
    this.age = 2;
  }
}

//Constructor create class
//function User (name,age){ this.name=name;this.age=age; }
class User {
  constructor(name, age) {
    //Private method
    this.name = name;
    this.age = age;
  }
  //Static method: a method that can be used without instantiating a class
  static getOne() {
    return 111;
  }
  //Prototype method
  //User.prototype.changeInfo=function(name,age){
  //this.name=name;
  //this.age=age;
  //}
  changeInfo(name, age) {
    this.name = name;
    this.age = age;
  }
  Info() {
    return this.name + ":" + this.age;
  }
}

//Subclass inheritance
class Manger extends User {
  constructor(name, age, password) {
    super(name, age); //Create the properties of the parent object before adding them to the child class
    this.password = password;
  }
  changePassword() {
    this.password = password; //Add new method
  }
  Info() {
    var info = super.info();
    return info + "--new";
  }
}

Ancient inheritance

// 1. The prototype chain inherits the parent (public + Private) = = > the child (public) cannot pass parameters to the parent constructor
B.prototype = new A(); //Disadvantages: the method of one instance is modified, and the methods of all instances are modified
B.prototype.constructor = B; //The built-in constructor attribute is lost because the prototype of B is modified

// 2. Call inherits parent (private) = > child (private) 	 Parameters can be passed to the parent class
function B() {
  A.call(this);
} //Modify this in the A function to the current instance of b, and then execute A.

// 3 copy inheriting parent (public + Private) = = > child (private) is inefficient, memory consumption is high, and the for in enumeration method cannot be obtained
//for in traversal can traverse the private properties of an instance or the artificially added public properties
function B() {
  var obj = new A(); //Example of A
  for (var key in obj) {
    this[key] = obj[key]; //Assign all properties and methods of the parent class instance to b at the same time
  }
  obj = null;
}

// 4 hybrid inheritance prototype + call 		 It is the perfect inheritance to pass parameters to the parent class
B.prototype = new A() || A.prototype || Object.create(A.prototype);
//Turn both private and public of A into public of B
B.prototype.constructor = B; //Complete the constructor property
function B() {
  A.call(this);
} //call inheritance turns A's private property into B's private property

ES6 publish subscribe mode

class EventEmiter {
  constructor() {
    this._events = {}; //Maintain an object
  }
  on(eventName, callback) {
    if (this._events[eventName]) {
      //If so, put a new one
      this._events[eventName].push(callback);
    } else {
      //If not, create an array
      this._events[eventName] = [callback];
    }
  }
  emit(eventName, ...rest) {
    if (this._events[eventName]) {
      //Cycle once
      this._events[eventName].forEach((item) => {
        item.apply(this, rest);
      });
    }
  }
  removeListener(eventName, callback) {
    if (this._events[eventName]) {
      //If the current array is equal to the passed callback, it will be removed
      this._events[eventName] = this._events[eventName].filter(
        (item) => item !== callback
      );
    }
  }
  once(eventName, callback) {
    function one() {
      //Run the original function in the one function, and only clear one
      callback.apply(this, arguments);
      this.removeListener(eventName, one); //Bind before deleting
    }
    this.on(eventName, one); //The emit trigger will execute this function and pass the rest parameter to this function
  }
}
class Man extends EventEmiter {}
let man = new Man();
function findGirl() {
  console.log("Find a new girlfriend");
}
function saveMoney() {
  console.log("save money");
  console.log("arguments" + JSON.stringify(arguments));
}
// man.once('lovelorn ', findGirl);
// man.on('lovelorn ', findGirl) / / lovelorn, bind a function method
man.on("Lovelorn", saveMoney); //Lovelorn, bind a function method
// man.removeListener('lovelorn ', saveMoney)// Remove a function method

event

  • Capture and bubbling: event capture is to determine the source of events layer by layer, and event bubbling is to respond to events level by level
  • In ie, document.getElementById("#test").attachEvent(type,listener);
    detachEvent(event,function);
function bindEvent(elem, type, fn) {
  elem.addEventListener(type.fn);
}
bindEvent(btn1, "click", (event) => {
  console.log(event.target); //Get triggered element
  event.preventDefault(); //Block default behavior
  alert("clicked");
});
// Prevent event bubbling: e.stopPropagation()
// Event agent: use event bubbling to bind the event to the parent element, and operate by judging event. Target. NodeName = = 'a'
function bindEvent(elem, type, selector, fn) {
  if (fn == null) {
    fn = selector;
    selector = null;
  }
  elem.addEventListener(type, (event) => {
    const target = event.target;
    if (selector) {
      //Proxy binding
      if (target.matches(selector)) {
        fn.call(target.event);
      }
    } else {
      //Normal binding
      fn.call(target, event);
    }
  });
}

Local object, built-in object, host object (this is all E, built-in does not have instances, and the host is not this, such as DOM)

  • Local objects: objects provided by ECMAScript, including new instantiatable objects such as Array Object RegExp and non instantiatable objects such as Math
  • Built in objects: Gload, Math, etc. cannot be instantiated (they are also local objects, and built-in objects are a subset of local objects)
  • Host object: all non local objects, all BOM and DOM objects are host objects, such as document,window and other objects provided by the browser

Page loading

  • onready is executed after page parsing is completed, while onload is executed after all elements of the page are loaded
  • When the DOM is loaded into the link tag, the css file is loaded in parallel with the DOM, that is, when the css is loaded, the DOM continues to load and build, and the css style or img encountered in the process will send a request to the server. After the resource is returned, it will be added to the corresponding position in the DOM;
  • Adding defer = "ture" in the script tag will make js and DOM load in parallel. After the page is loaded, the js file will be executed. In this way, there will be no blocking;
  • Add async = "ture" in the scirpt tag, which tells the browser that the js file is loaded and executed asynchronously, that is, it does not depend on other js and css, that is, the loading order of js files cannot be guaranteed, but it also has the effect of loading in parallel with DOM;
    When the defer and async attributes are used at the same time, the defer attribute will become invalid;
  • You can put the scirpt tag after the body tag, so that there will be no loading conflict.

ES6

  • Default value

    function f(x, y = 2, z = 4) {}
    f(1, undefined, 11); //y = undefined is the default value of 2
    
    function f(x, y = 9, z = x + y) {
      console.log(Array.from(arguments)); //Get the transmitted parameters
      console.log(f.length); //Directly take the length of the function to get the number of parameters without default value
    }
    
  • Rest parameter parameter

function sum(base, ...nums) {
  let num = 0;
  nums.forEach(function (item) {
    num += item * 1;
  });
  return base * 2 + num;
}
  • spread operation sum(...data)

  • Arrow function

    • When can't I use the arrow function

      // Methods for defining objects
      const calculator = {
        array: [1, 2, 3],
        sum: () => {
          console.log(this === window); // => true
          return this.array.reduce((result, item) => result + item);
        },
      };
      console.log(this === window); // => true
      // Throws "TypeError: Cannot read property 'reduce' of undefined"
      calculator.sum();
      
      // Define event callback function
      const button = document.getElementById("myButton");
      button.addEventListener("click", () => {
        console.log(this === window); // => true
        this.innerHTML = "Clicked button";
      });
      
      // Method of defining prototype
      function Cat(name) {
        this.name = name;
      }
      Cat.prototype.sayCatName = () => {
        console.log(this === window); // => true
        return this.name;
      };
      const cat = new Cat("Mew");
      cat.sayCatName(); // => undefined
      
      // You cannot define a constructor with an arrow function
      const Message = (text) => {
        this.text = text;
      };
      // Throws "TypeError: Message is not a constructor"
      const helloMessage = new Message("Hello World!");
      
  • Set data structure: duplicate data is not allowed. Data is a traversable object

    let s = new Set([1, 2, 3]);
    s.add(1).add(2);
    s.delete(1);
    s.clear(); //empty
    s.has(1); //true
    s.size;
    s.keys();
    s.values();
    s.entries(); //Return key value pair
    s.forEach(function (item) {});
    for (let item of s) {
      console.log(item);
    }
    
    // set de duplication array, cow!
    let newArr = [...new Set(arr)];
    
  • Map data structure: key can be any value, object or function

    let map = new Map([
      [1, 2],
      [3, 4],
    ]);
    
    map.set(2, 1);
    map.delete(1); // Delete key
    map.clear();
    map.size;
    map.has(1); // Check the value corresponding to the index
    map.get(1);
    map.keys();
    map.values();
    map.entries();
    map.forEach((value, key) => {});
    for (let [key, value] of map) {
    } //Only traversable objects can use for of
    
  • WeakSet: only objects can be saved

  • WeakMap: can only be a key of object type

  • object

    // You can write variables or expressions
    obj = { x, y, [z]: 6 };
    obj = {x, y, [x + z] };
    
    const target = {};const source = {b:3,a:4}; // The same attributes are overwritten and different attributes are copied
    Object.assign(target,source) // es6 data copies (shallow) are replaced with addresses of reference types and are not accurate to the difference
    Object.is(); // Are the two values equal
    Object.is(NaN,NaN);// true   NaN===NaN F
    Object.is({},{});// false   {}==={} F
    Object.is(+0,-0);// false   +0===-0 T
    
    // Object.is() considers the two values to be the same in the following cases:
    // Both values are undefined
    // Both values are null
    // Both values are true or both are false
    // Two values are strings composed of the same number of characters in the same order
    // Two values point to the same object
    // Both values are numbers and
    // Both are positive zero + 0
    // All negative zeros - 0
    // It's all NaN
    // All are the same number except zero and NaN
    
  • Template: template string

  • Destructuring assignment

    let arr = [1, 2];
    let [a, b] = arr;
    let [a, , b] = arr; // Skip an item,,
    let [a, , b] = new Set([1, 2, 3]);
    
    // Deconstruction assignment can assign not only variables, but also attributes of objects
    let user = ({ name: "s", username: "d" };
    [user.name, user.username] = [1, 2];
    for (let [k, v] of Object.entries(user)) {
      console.log(k, v);//[ [ 'name', 1 ], [ 'username', 2 ] ]
    }
    let [user, name, ...last] = arr; //1,2,[3,4,5]
    
    // Multidimensional array deconstruction
    let arr = [1,[2,3],4];
    let [a,[b,c],d]=arr;
    
    // Incomplete resolution
    let [a,[,c],d]=arr;
    
    // Variable exchange
    let x = 1,y=2;
    [y,x]=[x,y]
    
    // Set deconstruction assignment
    let [x,y] = new Set([1,2]) // x:1,y:2
    
    let [x,...y,6] = [1,2,3,4,5,6] // Rest element must be last element
    let [x,...y] = [1,2,3,4,5,6] // y:[2,3,4,5,6]
    
    // Deconstruction assignment of object
    let {name} = {name:'Q',age:21}
    console.log(name) // Q
    
    // Nested deconstruction: patterns cannot be printed, only variables can be printed
    let obj = {a:{b:{c:3}}}; // a. B is the mode, and only c is the variable that can be printed
    let {a:{b:{c}}} = obj
    console.log(c); // 3
    
    // Default value
    let [x=1,y]=[undefined,2] // x:1,y:2
    
    // Modify variable name
    let {name:myName} = obj
    console.log(myName)
    
    // character string
    let [a,b,c] = 'hello' // a:h   b:e  c:o
    
    // Parameters are arrays
    function test([x=1,y=2]=[],z=3){
      console.log(x,y,z)
    }
    test([],80)
    
  • Promise

function loadScript(src) {
  // pending,undefined
  return new Promise((resolve, reject) => {
    let script = document.createElement("script");
    script.src = src;
    script.onload = () => resolve(src); // fulfilled,result
    script.onerror = (err) => reject(err); // rejected,error
    document.head.append(script);
  });
}
loadScript("./1.js").then(loadScript("./2.js")).then(loadScript("./3.js"));
// . then is a method on the promise object prototype. Each time a promise instance is returned, two parameters need to be passed. If an empty promise object is not returned, it is guaranteed that the. Then method can be called continuously
// promise.then(onFulfilled,onRejected)

loadScript("./1.js")
  .then(
    () => {
      return loadScript("./4.js");
    },
    (err) => {
      console.log(err);
    }
  )
  .then(
    () => {
      loadScript("./3.js");
    },
    (err) => {
      console.log(err);
    }
  );

// promise static method
Promise.resolve(42); // The static value returned by the package can call the then method
Promise.reject(new Error("ss"));
// catch is also the method of the instance. catch exception handling. Then (). catch (ERR = > console. Log (ERR))

//Asynchronous parallelism
const p1 = Promise.resolve(1);
const p2 = Promise.resolve(20);
const p3 = Promise.resolve(3);
Promise.all([p1, p2, p3]).then((value) => {
  console.log(value);
});
Promise.race(); //First come, first served
const p1 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      resolve(1);
    }, 1000);
  });
};
const p2 = () => {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      resolve(2);
    }, 3000);
  });
};
Promise.race([p1(), p2()]).then((value) => {
  console.log(value);
});

//Promise Code:
const callAsync = (() => {
  let pending = false;
  let count = 1;
  let textNode = document.createTextNode(count);
  let tasks = [];
  let nextTickHandler = () => {
    pending = false;
    let cbs = tasks.slice(0);
    tasks = [];
    cbs.forEach((cb) => cb());
  };
  let observer = new MutationObserver(nextTickHandler);
  observer.observe(textNode, {
    characterData: true,
  });
  let nextTick = () => {
    count = (count + 1) & 1;
    textNode.data = count;
  };
  return (fn, args, cb, onError) => {
    let func = () => {
      try {
        cb ? cb(fn(args)) : fn(args);
      } catch (err) {
        onError(err);
      }
    };
    tasks.push(func);
    if (pending) return;
    pending = true;
    nextTick();
  };
})();

const PENDING = "pending",
  FULFILLED = "fulfilled",
  REJECTED = "rejected",
  isFunction = (fn) => typeof fn === "function";

class MyPromise {
  constructor(fn) {
    //Receive an executor execution function as a parameter, and the executor has two parameters resolve reject
    this._status = PENDING; //Initial state
    this._onFulfilledQueue = []; // Store the on fulfilled function corresponding to the completed state
    this._onRejectedQueue = []; // Stores the onRejected function corresponding to the rejected state
    this._value = null; // Information returned when the status is full
    this[Symbol.toStringTag] = "MyPromise";
    try {
      fn(this._resolve.bind(this), this._reject.bind(this)); //Execute excutor now
    } catch (err) {
      this._reject(err);
    }
  }
  _resolve(value) {
    //Value received in success status
    if (this._status !== PENDING) return;
    this._status = FULFILLED;
    const runFulfilled = (value) => {
      let fn;
      while ((fn = this._onFulfilledQueue.shift())) fn(value);
    };
    const runRejected = (error) => {
      let fn;
      while ((fn = this._onRejectedQueue.shift())) fn(error);
    };
    if (value instanceof MyPromise) {
      value.then(
        (res) => {
          this._value = res;
          runFulfilled(res);
        },
        (err) => {
          this._value = err;
          runRejected(err);
        }
      );
    } else {
      this._value = value;
      runFulfilled(value);
    }
  }
  _reject(error) {
    //Reason for receiving failure
    if (this._status !== PENDING) return;
    this._status = REJECTED;
    this._value = error;
    let fn;
    while ((fn = this._onRejectedQueue.shift())) fn(error);
  }
  then(onFulfilled, onRejected) {
    //onFulfilled the value of successful reception, and onrejectedthe reason for the failure of reception
    onFulfilled = isFunction(onFulfilled) ? onFulfilled : (res) => res; //Resolve (successful) onFulfilled call
    onRejected = isFunction(onRejected)
      ? onRejected
      : (err) => {
          throw err;
        }; //Reject (failed)
    return new MyPromise((onFulfilledNext, onRejectedNext) => {
      const resolve = (value) => {
        callAsync(
          onFulfilled,
          value,
          (res) => {
            if (res instanceof MyPromise) {
              res.then(onFulfilledNext, onRejectedNext);
            } else {
              onFulfilledNext(res);
            }
          },
          onRejectedNext
        );
      };
      const reject = (error) => {
        callAsync(
          onRejected,
          error,
          (res) => {
            if (res instanceof MyPromise) {
              res.then(onFulfilledNext, onRejectedNext);
            } else {
              onFulfilledNext(res);
            }
          },
          onRejectedNext
        );
      };
      switch (this._status) {
        case PENDING:
          this._onFulfilledQueue.push(resolve);
          this._onRejectedQueue.push(reject);
          break;
        case FULFILLED:
          resolve(this._value);
          break;
        case REJECTED:
          reject(this._value);
          break;
      }
    });
  }
  catch(onRejected) {
    //In chained writing, you can catch the exception sent in the previous then
    return this.then(null, onRejected);
  }
  static resolve(value) {
    return value instanceof MyPromise
      ? value
      : value && isFunction(value.then)
      ? new MyPromise((res) => res()).then(() => new MyPromise(value.then))
      : new MyPromise((res) => res(value));
  }
  static reject(error) {
    return new MyPromise((resolve, reject) => reject(error));
  }
  static all(list) {
    return new MyPromise((resolve, reject) => {
      let values = [],
        count = list.length;
      list.forEach((item, index) => {
        MyPromise.resolve(item).then((res) => {
          values[index] = res;
          --count == 0 && resolve(values);
        }, reject);
      });
    });
  }
  static race(list) {
    return new MyPromise((resolve, reject) => {
      list.forEach((item) => MyPromise.resolve(item).then(resolve, reject));
    });
  }
  static allSettled(list) {
    return new MyPromise((resolve) => {
      let count = list.length,
        values = [];
      list.forEach((item, index) => {
        MyPromise.resolve(item).then(
          (value) => {
            values[index] = {
              status: "fulfilled",
              value,
            };
            --count == 0 && resolve(values);
          },
          (reason) => {
            values[index] = {
              status: "rejected",
              reason,
            };
            --count == 0 && resolve(values);
          }
        );
      });
    });
  }
  finally(cb) {
    return this.then(
      (value) => MyPromise.resolve(cb()).then(() => value),
      (reason) =>
        MyPromise.resolve(cb()).then(() => {
          throw reason;
        })
    );
  }
}
  • Reflection mechanism: non reflection specifies the method first. Reflection is the method selected according to conditions during execution

    Is a built-in object that provides methods to intercept JavaScript operations

    const obj = { name: "abc", age: 18 };
    // Old:
    "name" in obj ? true : false;
    delete obj[age];
    Object.keys(obj);
    
    Reflect.has(obj, "name");
    Reflect.deleteProperty(obj, "age");
    Reflect.ownKeys(obj);
    console.log(Reflect.apply(Math.floor, null, [4.72]));
    console.log(
      Reflect.apply(price > 100 ? Math.floor : Math.ceil, null, [price])
    );
    let d = Reflect.construct(Date, []);
    console.log(d.getTime(), d instanceof Date);
    const student = {};
    const r = Reflect.defineProperty(student, "name", { value: "Mike2" });
    console.log(student, r);
    const obj = { x: 1, y: 2 };
    Reflect.deleteProperty(obj, "x");
    console.log(obj);
    console.log(Reflect.get(obj, "x"));
    console.log(Reflect.get([3, 4], 1)); //4
    console.log(Object.getOwnPropertyDescriptor(obj, "y"));
    let d = new Date();
    console.log(Reflect.getPrototypeOf(d)); //Look at the method on the prototype
    console.log(Reflect.has(obj, "y"));
    Object.freeze(obj); //Make obj not extensible
    console.log(Reflect.isExtensible(obj)); //Is it extensible
    // Own properties
    console.log(Reflect.ownKeys(obj));
    console.log(Reflect.ownKeys([1, 2])); //Returns the index and length
    Reflect.preventExtensions(obj); //Prohibit extension
    Reflect.set(obj, "z", 4);
    Reflect.set(arr, 2, "goose");
    Reflect.setPrototypeOf(arr, String.prototype); //Modify prototype object
    
  • Proxy proxy

    // Proxy protects original information
    let o = {
      name: 'xiaomi',
      price: 1999
    }
    let d = new Proxy(o, {
      get (target, key) {
        if (key === 'price') {
          return target[key] + 20
        } else {
          return target[key]
        }
      }
      set (target, key, value) {
        return false
      }
    })
    console.log(d.price, d.name)
    
    // es5 interception processing
    for (let [key] of Object.entries(o)) {
      Object.defineProperty(o, key, {
        writable: false
      })
    }
    
    // Listening error
    window.addEventListener('error', (e) => {
      console.log(e.message)
      // report('./')
    }, true)
    
  • Symbol: no duplicate values

    let name1 = Symbol("name");
    let name2 = Symbol("name");
    console.log(name1 === name2); // false
    
    const name = Symbol();
    const person = {
      [name]: "abc",
      say() {
        console.log(this[name]);
      },
    };
    person[name]; // 'abc'
    Symbol.for(); // Internal receive string Symbol.for(true)===Symbol.for('true ') / √
    
  • The iterator iterator calls the next() method to continue execution

    let arr = ["a", "b", "c"];
    let iterator = arr[Symbol.iterator()];
    console.log(iterator.next()); // {value:'a',done:false}
    console.log(iterator.next()); // {value:'b',done:false}
    console.log(iterator.next()); // {value:'c',done:false}
    console.log(iterator.next()); // {value:undefined,done:true}
    console.log(iterator.next()); // {value:undefined,done:true}
    
  • Generator with * fn

    • Functions with *
    • The function uses yield internally to pause execution. When it encounters yield, execution stops. The value after yield is used as the value of next
    • When calling, use next() to resume the function execution, find the yield in the function or pause the end function
    function * fn(){
      console.log('foo');
      returen 'bar'
    }
    // The generator executes generating an iterator
    let it = fn()
    let res = it.next()
    console.log(res)
    
    // Using yield segments in the generator:
    function * fn(){
      yield 1;
      yield 2;
      yield 3;
    }
    let it = fn;
    console.log(it.next()) // {value:1,done:false}
    console.log(it.next()) // {value:2,done:false}
    console.log(it.next()) // {value:3,done:false}
    console.log(it.next()) // {value:undefined,done:true}
    
    for (let v of it){
      console.log(v)
    }  //1 2 3 only the value with done as false will be printed
    
    function * loop () {
      for (let i = 0; i < 5; i++) {
        yield console.log(i) //yield keyword
      }
    }
    const l = loop()
    // Scenario: lottery / custom traverser
    l.next() 0
    l.next() 1
    l.next() 2
    l.next() 3
    l.next() 4
    l.next()
    
    function * gen () {
      let val
      val = yield 1
      console.log(val)
    }
    const l = gen()
    l.next() // When the yield execution stops, the following is 1, so it will not be printed
    l.next() //The undefined function has ended and no yield has been found. The yield expression has no value and returns undefined
    
    function * gen () {
      let val
      val = yield * [1, 2, 3] //Add \ * to indicate that the following is a traversable object
      console.log(val)
    }
    // next(): returns the value of the current data and whether to end {value:1,done:false}
    l.next(10)
    console.log(l.return(100)) //return {value:100,done:true}
    l.next(20) // 20 modify the return value of yield by passing the value next
    
    function * gen () {
      while (true) {
        try {
          yield 1
        } catch (e) {
          console.log(e.message)
        }
      }
    }
    const g = gen()
    console.log(g.next())
    console.log(g.next())
    console.log(g.next())
    console.log(g.next())
    g.throw(new Error('ss')) //Continued execution will not affect a similar continue
    console.log(g.next())
    
  • Module: modular design

    // export
    export const name = 'hello'
    export let addr = 'Beijing'
    export var list = [1, 2, 3]
    // Import
    import { name, addr, list } from './name.js'
    
    // Export together
    export default name
    export {
      addr,
      list
    }
    import name, { addr, list } from './name.js'
    
    // Import rename: by default, the name can be changed directly for export, {} export should be renamed with as
    import name2, { addr as addr2, list } from './name.js'
    
    // Function export
    const say = (content) => {
      console.log(content)
    }
    const run = () => {
      console.log('i am running')
    }
    //Introduction function
    import { say, run } from './say.js'
    
    export default say
    export {
      run
    }
    //The default export is placed outside curly braces
    import say { run } from './say.js'
    
    // Default export object
    export default {
      code:1,
      message:'success'
    }
    import obj form './obj.js'
    
    // Export multiple objects:
    const data = {
      code: 1,
      message: 'success'
    }
    const des = {
      age: 20,
      addr: 'Beijing'
    }
    export default {
      data,
      des
    }
    import obj from './data.js'
    let {data, des} = obj
    
    //Default export of class
    export class Test {
      constructor () {
        this.id = 6
      }
    }
    export class Animal {
      constructor () {
        this.name = 'dog'
      }
    }
    export default class People {
      constructor () {
        this.id = '132'
      }
    }
    import { Test, Animal  }form './test.js'
    
    // Import all modules with an alias
    import * as Mod from './mod'
    let test = new Mod.Test()
    console.log(test.id)
    let animal = new Mod.Animal()
    console.log(animal.name)
    let people = new Mod.default()
    console.log(people.id)
    
  • ES8: async await

  • ES9: For await of: asynchronous collection traversal, Promise.finally()

    function Gen(time) {
      return new Promise((resolve, reject) => {
        setTimeout(function () {
          resolve(time);
        }, time);
      });
    }
    async function test() {
      let arr = [Gen(2000), Gen(100), Gen(3000)]; //All asynchronous operations
      for (let item of arr) {
        console.log(Date.now(), await item.then(console.log));
      }
    }
    
    async function test() {
      let arr = [Gen(2000), Gen(100), Gen(3000)];
      for await (let item of arr) {
        console.log(Date.now(), item);
      }
    }
    
  • Rest and Spread of objects in ES9

    const output = {
      ...input, // spread is made in the form of copy, not reference address. Modifying the original object will not affect the current
      ...test,
      c: 3,
    };
    

The difference between commonjs and es6 modularity

  • The CommonJS module outputs a copy of the value, and the ES6 module outputs a reference to the value.
  • CommonJS module is loaded at run time, and ES6 module is the output interface at compile time.
  • CommonJs is a single value export, and ES6 Module can export multiple values
  • CommonJs is a dynamic syntax that can be written in the judgment, and ES6 Module static syntax can only be written at the top level
  • This of CommonJs is the current module, and this of ES6 Module is undefined
  • CommonJS (synchronously loaded at runtime, copying objects in the module, shallow copy)

    • The module can be loaded multiple times, but it will only be loaded for the first time, and then it will be cached. The values in the cache are introduced
    • Import and use: require("path")
    • 1. If it is a third-party module, you only need to fill in the module name
    • 2. Self defined modules need to use relative paths or absolute paths
    • Export module: exports.xxx or module.exports.xxx or module.exports=xxx or this.xxx
    • !! Whether you use exports or this, you need to export in the form of point syntax, because they are the pointers of module. - exports. Re assignment will cut off the association
  • ES6 Module ([ dynamic read-only reference ], which is loaded asynchronously during compilation and has an independent module dependent parsing stage. ES6 Module is a reference to the module, that is, ES6 Module only saves read-only and cannot change its value. Specifically, the pointer cannot be changed, similar to const.)

    • export default variable or function or object is exported by default
    • import name from "relative or absolute path" is imported by default
    • The exported name and the imported name can be different
    • export on demand requires declaration of variables const var let function function
    • import {variable name or function name} form "path" as needed
    • Import all use import * as to customize the name "path"
    • The default export and on-demand export are all imported

js macro task and micro task

When suspending a task, the JS engine will divide all tasks into these two queues according to categories. First, take out the first task in the macrotask queue (this queue is also called task queue), and then take out all tasks in the microtask queue for sequential execution after execution; Then take the macrotask task task again and again until the tasks in both queues are taken.

  • Synchronization task: enter the main process for execution

  • Asynchronous task: enter the Event table registration function. When the specified task is completed, ET will move the task to the Event Queue. The main process task is empty after execution. Go back to EQ to read, enter the main process for execution, and repeat this process continuously, which is js Event Loop

  • Macro tasks: setTimeout, setInterval, requestAnimationFrame(web), setImmediate(node)

  • Micro tasks: Promise.then catch finally, MutationObserver(web), process.nextTick(node)

setTimeout(() => {
  console.log("Inner macro event 4"); //Callback a macro event after execution
}, 0);
console.log("Outer macro event 1");
new Promise((resolve) => {
  console.log("Outer macro event 2");
  resolve();
})
  .then(() => {
    console.log("Micro event 1");
  })
  .then(() => {
    console.log("Micro event 2");
  });
console.log("Outer macro event 3");
// Outer macro event 1 outer macro event 2 outer macro event 3 micro event 1 micro event 2 inner macro event 4
// First, the browser executes js to enter the first macro task into the main thread, encounters setTimeout and distributes it to the macro task Event Queue
// Event 1 when console.log() executes output macro directly
// When Promise is encountered, new Promise directly executes the output macro event 2
// Event 3 when console.log() executes output macro directly
// The execution then is distributed to the micro task Event Queue
// After the first round of macro task execution, start to execute micro task and print 'micro event 1' and 'micro event 2'
// After the execution of the first round of micro tasks, execute the second round of macro events and print the content 'inner macro event 4' in setTimeout

console.log("1"); //The main thread executes directly
setTimeout(function () {
  //Drop into macro event queue
  console.log("2"); //1
  process.nextTick(function () {
    console.log("3"); //3
  });
  new Promise(function (resolve) {
    console.log("4"); //2
    resolve();
  }).then(function () {
    console.log("5"); //4
  });
});
process.nextTick(function () {
  console.log("6"); //Micro event 1
});
new Promise(function (resolve) {
  console.log("7"); //The main thread executes directly
  resolve();
}).then(function () {
  console.log("8"); //Micro event 2
});
//Drop into macro event queue
setTimeout(function () {
  console.log("9"); //1
  process.nextTick(function () {
    console.log("10"); //3
  });
  new Promise(function (resolve) {
    console.log("11"); //2
    resolve();
  }).then(function () {
    console.log("12"); //4
  });
});
// The complete output of the browser is 1, 7, 6, 8, 2, 4, 3, 5, 9, 11, 10, 12
// First, the browser executes js, enters the first macro task, enters the main thread, and directly prints console.log('1 ')
// Encountered setTimeout and distributed to macro task Event Queue
// process.nextTick is encountered and thrown into the micro task Event Queue
// If Promise is encountered, new Promise directly executes the output console.log('7 ');
// The execution then is distributed to the micro task Event Queue
// After the first round of macro task execution, start micro task printing 6,8
// After the execution of the first round of micro tasks, execute the second round of macro events and execute setTimeout
// First execute the macro task of the mainline program, and then print '2,4,3,5' after executing the micro task
// When executing the second setTimeout, print '9,11,10,12' similarly
// Summary: first execute the macro task = = > micro task of the main process and execute the next queue

Asynchronous and single threaded

  • js is a single thread and can only do one thing
  • Browsers and nodejs already support js startup processes, such as web worker
  • JS and DOM rendering share one thread, because JS can modify the DOM structure (one must be done and the other must be stopped)
  • Asynchronous: (callback callback function) does not block code execution. Scenario: 1. Network request 2. Timer
  • Synchronization: alert() blocks code execution

js operation DOM

document.getElementById("div1");
doecument.getElemntsdByTagName("div"); //aggregate
document.getElementsByClassName("div1"); //aggregate
document.querySelectorAll("p"); //aggregate
//Compatible with all browsers to obtain screen width and height
let curWidth =
  document.documentElement.clientWidth || document.body.clientWidth;
let curHeight =
  document.documentElement.clientHeight || document.body.clientHeight;
  • Node type

    namenodeTypenodeNamenodeValue (node value)
    element1Upper case label namenull
    text3#textText content
    notes8#commentNote Content
    document9#documentnull
  • Node Relationship Attribute in DOM:

    • childNodes gets all child nodes, including elements, text, line breaks, spaces, comments and other array types
    • children get all the element child nodes (label elements). The lower version browser can get the annotation node ie8
    • firstChild gets the first child node
    • fistElementChild gets the child node of the first element
    • lastChild gets the last of all child nodes
    • lastElementChild
    • parentNode get parent node
    • previousSibling get older brother (previous) node (text, comment, element)
    • Element node of previousElementSibling
    • nextSibling gets the sibling node (text, comment, element)
    • Nextlementsibling element node
    • The worst thing you can't get in HTML is null. You haven't seen undefined.
  • property: modify js variables and object properties in the form of js attribute operation, which will not be reflected in the setting of p1.style.width(className) or obtaining page style in html structure

  • attr: set the tag attribute, modify the dom node attribute input, and modify the html attribute, which will be reflected in html

    p1.setAttribute("data-name", "icc");
    p1.getetAttribute("data-name"); //icc
    p1.setAttribute("style", "color:red");
    
  • Property will avoid some duplicate dom rendering than attr, and try to use property

    // New node: createElement
    const p1 = document.createElement("p");
    p1.innerHtml = "this is p1";
    // Inserting and moving nodes: appendChild
    div1.appendChild(p1);
    // Get parent element: parentNode
    console.log(p1.parentNode);
    // Get child element list: childNodes
    console.log(div1.childNodes); //Include text elements
    // Insert before (a, b)
    insertBefore(a, b);
    // The parameter is the element parentNode.removeChild(oA) to be deleted; Parent delete
    div1.removeChild(child[0]);
    // A who will replace new b who will replace old the point is to move the parent. replaceChild(a,b)
    replaceChild(a, b);
    // Clone node true: copy the content together
    cloneNode() / cloneNode(true);
    // Get p tag
    const childP = Array.prototype.slice.call(div.childNodes).filter((child) => {
      if (child.nodeType === 1) {
        return true;
      }
      return false;
    });
    
  • DOM performance: cpu consumption

    • 1. Do a cache: pay the dom node to a variable
    • 2. Change frequent operation to one-time operation
      // Document fragment
      // Create a file fragment that is not inserted into the DOM at this time
      const frag=document.createDocumentFragment()
      for(let i=0,i<10,i++){
        const li = document.createElement('li')
        li.innerHTML='this is li'
        frag.appendChild(li)
      }
      // One time insertion
      nodeList.append(frag)
      
  • BOM

    // How to identify browser type navigator screen location history
    const ua = navigator.userAgent;
    const isChrome = ua.indexOf("Chrome");
    console.log(screen.width); //Width and height of the screen
    location.href; //website
    location.protocol; //agreement
    location.host; //domain name
    location.search; //Query parameters
    location.hash;
    location.pathname;
    history.back();
    history.forward();
    

Ajax (Asynchronous JavaScript And XML)

// ajax: XMLHttpRequest
const xhr = new XMLHttpRequset();
xhr.open("GET", "/data/test.json", true); // true is asynchronous
xhr.onreadystatechange = function () {
  if (xhr.readyState === 4) {
    if (xhr.status === 200) {
      console.log(xhr.responseTest);
    }
  }
};
xhr.send(null);
// post request:
const postData = {
  userName: "aa",
  password: 123,
};
xhr.send(JSON.stringify(postData));
  • xhr.readyState:

    • 0 - uninitialized and unused send() method
    • 1 - the send method has been called in loading, sending the request
    • 2 - load completed, send method execution completed, and all corresponding contents have been received
    • 3 - the interaction is parsing the corresponding content
    • 4 - the corresponding content is parsed and can be called on the client
  • Homology strategy: according to the requirements of the browser, the web page and server must be homologous, and the protocol, domain name and port are consistent.

    • img can be used for statistical management, and third-party statistical services can be used
    • link and script can use CDN, which is generally a foreign domain
    • script can realize JSONP and also needs the cooperation of the server. The server can splice any data to return
  • Solve cross domain

    • The principle of jsonp is to use the < script > tag without homology policy restrictions, send a get request with callback parameters through the src attribute of the < script > tag, and the server will piece up the interface return data into the callback function and return it to the browser. The browser will parse and execute it, so that the front end can get the data returned by the callback function. Only one request can be sent
    • Cross domain resource sharing (CORS) access control allow origin:*
    • Proxy of proxy nginx vue
    • postMessage
    • webSocket
    // jsonp can only send get one request
    let script = document.createElement('script');
    script.type = 'text/javascript';
    // Pass a callback function name to the back end to facilitate the execution of the callback function defined in the front end when the back end returns
    script.src = 'http://localhost:8080/login?user=admin&callback=handleCallback';
    document.head.appendChild(script);
    // Callback execution function
    function handleCallback(res) {
      console.log(JSON.stringify(res));
    }
    // The server returns the following (the global function is executed when it returns):
    handleCallback({"success": true, "user": "admin"})
    
    // jsonp
    window.callback = function (data) {
      console.log(data);
    };
    <script src="http://localhost:8080/jsonp.js"></script>;
    //Content of jsonp.js: execute this function and take the content back
    callback({ name: "abc" });
    
    // The CORS server can set the response header fields that can be set for cross domain CORS requests, starting with access control -, access control allow origin: required
    
    // #proxy server
    // server {
    //     listen       81;
    //     server_name  www.domain1.com;
    
    //     location / {
    //         proxy_ pass    http://www.domain2.com:8080 # Reverse proxy
    //         proxy_cookie_domain www.domain2.com www.domain1.com; # Modify the domain name in the cookie
    //         index  index.html index.htm;
    
    //         #When using middleware proxy interfaces such as webpack dev server to access nignx, there is no browser participation at this time, so there is no homology restriction. The following cross domain configuration can not be enabled
    //         add_ header Access-Control-Allow-Origin  http://www.domain1.com # When the current end only spans domains without cookie s, it can be*
    //         add_header Access-Control-Allow-Credentials true;
    //     }
    // }
    
    let myAjax = function (url, method, type, data) {
      if (!url) {
        return Promise.reject(new Error("url Cannot be empty!"));
      }
      if (!method) {
        method = "GET";
      }
      if (!type) {
        type = "application/json";
      }
      if (
        type === "application/x-www-form-urlencoded" &&
        typeof data === "object"
      ) {
        let str = "";
        Object.keys(data).forEach((x) => {
          str += `${x}=${data[x]}&`;
        });
        data = str.replace(/&$/, "");
      }
      return new Promise((resolve, reject) => {
        let xhr = new XMLHttpRequest();
        xhr.open(method, url);
        xhr.setRequestHeader("Content-Type", type);
        xhr.setRequestHeader("access-token", cfg.accessToken);
        xhr.send(data || null);
        xhr.onreadystatechange = function () {
          if (xhr.readyState === this.HEADERS_RECEIVED) {
            console.log(`Content-Type: ${xhr.getResponseHeader("Content-Type")}`);
          } else if (xhr.readyState === 4) {
            if (xhr.status === 200) {
              return resolve(xhr.response);
            } else {
              return reject(xhr.response);
            }
          }
        };
      });
    };
    // Using ajax in jquery
    $.ajax({
      type:'POST',
      contentType:'application/json;charset=UTF-8',
      url:'http://127.0.0.1/admin/list',
      data:JSON.stringify(list),
      jsonpCallback: "handleCallback",  // Custom callback function name
      success:function(){},
      error:function(){}
    })
    fetch(url).then(): //The returned Promise will not be marked as reject. 404 and 500 will be returned in time. Reject will be returned only in case of network failure. No cookies will be sent and received from the server. The credentials option must be set
    //axios:axios.get().then()
    

storage

  • cookie: it is used for communication between the browser and the server. It can be used for local storage. It can be modified with document.cookie = "a=100". The maximum limit is 4kb. It should be sent to the server every time to increase the amount of requested data,
  • localStorage: permanent storage, H5 specially designed storage, with a maximum storage capacity of 5M. The API is simple: setItem getItem, which is not sent with http request
  • sessionStorage: only the current session exists, and it will be cleared when the browser is closed

linux commands:

  • ssh user@192.168.2.97 =>Enter enter password
  • ls View Folder
  • ls -a view all
  • Look at the list of cars
  • clear
  • mkdir file
  • rm -rf file delete folder
  • cd dist
  • mv 1.js 2.js modify the file name
  • mv 1.js... /... / product/1.js move files
  • cp 1.js 2.js copy
  • rm a1.js delete the file a1.js
  • touch a2.js create file
  • vi d.js edit file i input: wq write exit q! Force exit without saving
  • vim can be opened directly if there is one, and can be created and opened if there is no one
  • cat package.json viewing
  • head package.json view the first few lines
  • tail package.json view the last few lines
  • grep 'babel' package.json search keyword

Garbage in JS

  • 1. js memory management is automatic
  • 2. Objects are garbage when they are not referenced
  • 3. The object cannot be accessed from the root. It is garbage (unreachable)

GC: short for garbage collection mechanism, it can find garbage in memory and free and recycle space

  • GC algorithm:

    • 1. Reference count: sets the number of references to determine whether the current number of references is 0

      Reference counter = = > reference relation change modify reference number = = > reference number is 0, recycle immediately

      • Advantages: garbage is collected immediately when it is found, and program suspension is minimized
      • Disadvantages: the circular reference object cannot be recycled, and the time overhead is large
        function fn() {
          const obj1 = {};
          const obj2 = {};
          boj1.name = obj2;
          obj2.name = obj1;
        }
        fn();
        
    • 2. Mark clear

      It is divided into two stages: marking and clearing. It traverses all objects, finds marked active objects, traverses all objects, clears unmarked objects, and reclaims the corresponding space

      • Advantages: solve the circular reference operation of objects
      • Disadvantages: space fragmentation and discontinuous recycled addresses
    • 3. Marking arrangement

      The enhancement of mark clearing. In the clearing phase, finishing is performed first to move the position of the object

      • Disadvantages: garbage objects are not collected immediately
      • V8 engine: timely compilation is adopted, so fast memory limit: 1.5g/800m
    • Generation recycling

      Memory is divided into new generation and old generation, including space replication, mark clearing, mark sorting and mark increment

      • Cenozoic (From used space, To free space): objects with short survival time and small space storage (32M/16M)
      • The new generation recycling adopts replication algorithm + tag sorting. The active object is in the from space. After tag sorting, the active object is copied to the to space, and the from and to exchange spaces are released. (Replication Algorithm: space for time). The new generation surviving in a round of GC needs to be promoted to the old generation space. If the use of to space exceeds 25%, it will also be promoted
      • Old generation: mainly use mark clearing for GC. When the promotion space of the new generation is insufficient, mark sorting is carried out, and mark increment is optimized for efficiency. (Mark increment and program are executed alternately, with part executed and part marked)
    • Performance tools monitor memory

    • Memory monitoring mode:

      • Memory leak: memory continues to rise without falling
      • Memory bloat: performance issues on most devices
      • Frequent garbage collection: memory change graph analysis
      • Browser Task Manager: shift+esc
      • Timeline timing chart record: Performance
      • Heap snapshot lookup separation DOM: console memory, heap snapshot
      • Judge whether there is frequent garbage collection: the Timeline rises and falls frequently, and the task management data increases and decreases frequently
  • Code optimization:

    • 1. Use global variables with caution: at the top of the scope chain, there is an execution stack until the end, and the local scope pollutes the global with the same name
    • 2. Cache global variables: get dom and store it in variables
    • 3. Adding methods through prototypes
    • 4. Avoiding closure traps
    • 5. Avoid using property access methods
    • 6. for loop optimization, select the optimal loop method
    • 7. Document fragment, clone, optimization node
    • 8. Directly replace the new Object definition with literal

Exception caught in JS:

  • 1. Manually capture try {} catch (ERR) {} finally {}
  • 2. Auto capture:
window.onerror = function (message, source, lineNum, colNum, error) {
  // For cross domain js, such as CDN, there will be no detailed error reports
  // For compressed js, you need to reverse query uncompressed rows and columns with sourceMap
};

RAF requestAnimationFrame

For smooth animation, the update frequency should be 60 frames / s, that is, the view should be updated once in 16.67ms. The setTimeout should manually control the frequency, and the RAF browser will automatically control it. In the background label or hidden iframe, the RAF will pause, and the setTimeout will still be executed

// 3s change the width from 100px to 640px, that is, increase 540px
// 60 frames / s, 3s 180 frames, 3px each time
const $div1 = $("#div1");
let curWidth = "100px";
const maxWidth = "640px";
function animate() {
  curWidth = curWidth + 3;
  $div1.css("width", curWidth);
  if (curWidth < maxWidth) {
    setTimeout(animate, 16.7); //Manual control time
    //The window.requestAnimationFrame(animate) browser automatically controls the time
  }
}
animate();

Browser cache: DNS cache and page resource cache are used in two places

  • 1.DNS caching is relatively simple, which is to associate the corresponding IP and domain name locally in the browser

    Browser cache - > system cache - > local host file (set as read-only as far as possible) - > DNS system call requests the local domain name server localDNS (LDNS) to resolve the domain name (80% can be found) - > direct request

  • 2. Browser resource cache

    • Strong cache

      Instead of requesting the server, read directly from the cache. Chrome = > network can see that the request returns 200, and the Size displays from disk cache or from memory cache. Strong caching can be achieved by setting two HTTP headers: Expires and cache control

      • Expires: cache expiration time, which specifies the expiration time of resources. It is the specific time point on the server side.

        Expires = max age + request time, which should be used in combination with last modified. Expires is the header field of the Web server response message. When responding to the http request, it tells the browser that the browser can directly fetch data from the browser cache before the expiration time without requesting again.

        Expires is a product of HTTP/1. It is limited by the local time. If the local time is modified, the cache may become invalid.

      • Cache control: a product of HTTP/1.1. For example, if you set cache control: Max age = 300 and load resources again within 5 minutes, you will hit the strong cache.

        More options for cache control:

        No cache: indicates that the cache control method of cache control is not used for pre verification, but Etag or last modified fields are used to control the cache. After no cache is set, it does not mean that the browser will no longer cache data, but the browser needs to confirm whether the data is consistent with the server before using the cached data. Negotiation cache used

        No store: all contents will not be cached, that is, neither forced cache nor negotiation cache will be used

      • Difference: Expires is the product of http1.0 and cache control is the product of http1.1. If both exist at the same time, cache control has higher priority than Expires.
      • Strong caching determines whether to cache based on whether it exceeds a certain time or a certain period of time, regardless of whether the server-side file has been updated, which may cause the loaded file to be not the latest content on the server-side. At this time, we need to use the negotiated caching strategy.
    • Negotiation cache

      After the strong cache fails, the browser sends a request to the server with the cache ID, and the server determines whether to use the cache according to the cache ID, mainly in the following two cases:

      When the negotiation cache takes effect, 304 and Not Modified are returned

      If the negotiation cache fails, 200 and the request result are returned

      The negotiation cache implements last modified and ETag by setting two HTTP header s

      • Last modified (returned by the server) and if modified since (brought when requested)

        When the browser accesses the resource for the first time, while the server returns the resource, the last modified header is added to the response header, indicating the last modification time of the resource on the server. The browser caches the file and header after receiving it; Last-Modified: Sun, 31 May 2020 05:28:04

        When the browser requests resources next time, it detects the last modified header and adds the if modified since header. The value is the value in last modified; The server will compare the value in if modified since with the last modification time of the resource in the server. If there is no change, 304 and empty response bodies will be returned and read directly from the cache. If the time of if modified since is less than the last modification time of the resource in the server, it indicates that the file has been updated, so a new resource file and 200 status code will be returned

        Last modified disadvantages:

        • 1. If the cache file is opened locally, even if the file is not modified, the last modified will be modified, and the server cannot hit the cache, resulting in sending the same resource
        • 2. Last modified can only be counted in seconds. If the file is modified within 1s, the server will think that the resource is still hit and will not return the correct resource

        Therefore, ETag and if none match appear in HTTP / 1.1

      • ETag and if none match

        The process is similar to the above. ETag is a unique identifier (generated by the server) of the current resource file returned by the server when responding to the request. ETag will be regenerated as long as the resource changes. When the browser sends a request to the server the next time it loads a resource, it will put the ETag value returned last time into the if none match in the request header. The server only needs to compare whether the if none match transmitted by the client is consistent with the ETag of the resource on its own server, so as to judge whether the resource has been modified relative to the client. If the server finds that the etags do not match, it directly returns 200 and sends new resources (including new etags of course) to the client; If the etags are consistent, 304 is returned directly, and the client can directly use the local cache.

      • Comparison between the two: last modified is the product of HTTP/1.0, while Etag is the product of HTTP/1.1. In terms of accuracy, Etag is better than last modified. In terms of performance, Etag is inferior to last modified. After all, last modified only needs to record time, and Etag needs the server to calculate a hash value through algorithm. In terms of priority, Etag is preferred for server verification

    • Summary: the mandatory cache takes precedence over the negotiation cache. If the mandatory cache takes effect, the cache will be used directly. If it does not take effect, the negotiation cache will be used. The server will decide whether to use the cache. If the negotiation cache fails, the requested cache will fail, return 200, re return the resource and cache ID, and then store it in the browser cache; If it takes effect, it returns 304 and continues to use the cache.

    • Impact of user behavior on browser cache:

      • 1. Enter the address in the address bar: check whether there is a match in the disk cache. Use if necessary; If not, send a network request.
      • 2. Normal refresh (F5): because TAB is not closed, memory cache is available and will be used first, followed by disk cache.
      • 3. Forced refresh (Ctrl + F5): the browser does not use cache, so the request headers sent are all provided with cache control: no cache (pragma: no cache is also provided for compatibility), and the server directly returns 200 and the latest content.

babel Compilation Principle

  • babylon parses the ES6/ES7 code into AST
  • Babel traverse traverses and translates the AST to obtain a new ast
  • The new AST is converted to ES5 through Babel generator

Function coritization

In a function, the technique of first filling in several parameters and then returning a new function is called function coritization. Generally, it can be used to preset general parameters for functions for repeated calls without invading functions.

const add = function add(x) {
  return function (y) {
    return x + y;
  };
};
const add1 = add(1);
add1(2) === 3;
add1(20) === 21;

Tags: Javascript Front-end Interview

Posted on Sat, 30 Oct 2021 00:42:16 -0400 by plasmagames