JS handwriting correlation

Call, apply, bind

1. What is the difference between the three functions?

Binds a function to a context that changes what this points to in the function.

  • fun.call(thisArg,arg1,arg2…)
  • fun.apply(thisArg,[arg1,arg2…] )
  • fun.bind(thisArg,arg1,arg2…)

Parameters: thisArg(optional):

  1. Fun’s this points to thisArg object
  2. In non-strict mode: thisArg is specified as null, undefined, and this in fun points to the window object.
  3. In strict mode: fun this is undefined. This refers to an autowrapped object with a primitive value (Number, String, Boolean), such as String, Number, Boolean

Param1,param2(Optional): parameters passed to fun.

  1. If param is not passed or null/undefined, no arguments need to be passed.
  2. The second argument to apply is an array, and the values in the array are the arguments passed to Fun.

The difference between

  1. Call passes the 2nd to n arguments to fun, and the 2nd argument to apply is an array.
  2. Call /apply calls a function with a given value of this and executes the function immediately after changing the context of this. The bind, bind() method creates a new function that executes this as the first argument to bind when bind() is called. It is not immediately executed, but needs to be called again to execute the function.

example

var a ={
    name:'cherry'.age:'18'.say:function(school){
        console.log(this.name+'_'+this.age+'_'+school); }}var b={
    name:'kitty'.age:'the'
}

a.say.call(b,'MIT1'); // Call, bind this value, and pass the school argument
a.say.apply(b,['MIT2']); // Call apply, bind this value, and pass the school argument as an array
a.say.bind(b,'MIT3') ();//bind is called to bind this value and pass in the school argument
Copy the code

2. Handwriting to achieve three functions

(1) Handwritten implementation of call

1. Set the context object (this points to) according to the call rules. Implicitly bind the function’s this pointer to the context by setting the context property 3. 4. Delete temporary attributes and return the result of function execution

implementation

Function.prototype.myCall = function (context, ... args) {
    if(context === null || context === undefined){
        context=window;
    }// According to the MDN definition, this value specified as null/undefin will automatically refer to the global object (browser is window).
    else{
        context=Object(context); // This with a primitive value (number, string, Boolean) refers to an instance object of that primitive value
    }
    const fn = Symbol(a);// Returns a value of type Symbol. The Symbol value can be used as an identifier for an object property to prevent overwriting the property and be used for temporary storage functions
    context[fn] = this; // The function's this is implicitly bound to context
    letresult = context[fn](... args);// Execute functions with implicit binding and pass arguments

    delete context[fn]; // Delete the properties of the context object
    return result;
        }
Copy the code

validation

/ / validation:
var a = {
    name: 'cherry'.age: '18'.say: function (school){
    console.log(this.name + '_' + this.age + '_' + school)
    }
}
var b = {
    name: 'kitty'.age: 'the'
}

a.say.myCall(b,'MIT1')
Copy the code

The results of

(2) Handwritten implementation of Apply

This is similar to call, except that the parameters are passed differently

Function.prototype.myCall = function (context, args) {
    if(context === unll || context === undefined){
        context=window;
    }// According to the MDN definition, this value specified as null/undefin will automatically refer to the global object (browser is window).
    else{
        context=Object(context); // This with a primitive value (number, string, Boolean) refers to an instance object of that primitive value
    }
    const fn = Symbol(a);// Returns a value of type Symbol. The Symbol value can be used as an identifier for an object property to prevent overwriting the property and be used for temporary storage functions
    context[fn] = this; // The function's this is implicitly bound to context
    letresult = context[fn](... args);// Execute functions with implicit binding and pass arguments

    delete context[fn]; // Delete the properties of the context object
    return result;
        }
Copy the code

(3) Handwritten implementation of BIND

(2) Use object. create to copy the prototype of the source function to newf 2. (2) Bind this+ pass argument (3) Return the result of the execution of the source function

implementation

Function.prototype.myBind = function(context,... args1){
    const self = this; // Record this value
    let newf = function(){
Var result =new newf()
// True: this refers to an instance object
// If not, it is called directly by ()
    const res=this instanceof newf? this : Object(context); 
    return self.apply(res,args1.concat(Array.prototype.slice.call(arguments)));
    }
// Use the prototype chain to chain them together to ensure that the attributes on the prototype object of the original function are not lost.
    newf.prototype = Object.create(self.prototype);
    return newf;
}
Copy the code

The test results

// Consider that bind has two different arguments objects
// In bind, this refers to b
// resultB=new B() // But after new this points to a resultB -- >new, this points to the instantiated object
console.log("System comes with bind results")
var A = a.say.bind(b, 'MITTT1') ();var B = a.say.bind(b,'MIT2')
var resultB = new B()

console.log("I wrote my own bind result.")
var C = a.say.myBind(b, 'MIT1') ()var D = a.say.myBind(b,'MIT3');
var resultD = new D();
Copy the code

2. The new implementation

1. What does the new operation achieve

The MDN: new operator creates an instance of a user-defined object type or of a built-in object with a constructor. When new Foo(…) Something will happen

  1. Create a new object that inherits from foo. prototype.
  2. Call the constructor Foo with the specified arguments and bind this to the newly created object.
  3. The object returned by the constructor is the result of the new expression. If the constructor explicitly returns an object, that object is used as the result. If it does not explicitly return an object, the new object inherited from Step 1 is used as the result.

implementation

function myNew(ctor, ... args) {
    if (typeofctor ! = ='function') {
        throw new TypeError('TypeError');
    }
// 1. Create a new object inherited from ctor. Prototype
    const obj = Object.create(ctor.prototype);
// 2. Call the constructor with the specified arguments and bind this
    const res = ctor.apply(obj, args)
// 3. Determine the returned content. If it is an object, use it directly; otherwise, use the newly created object
    const isObj = typeof res === 'object'&& res ! = ='null';
    const isFunc = typeof res === 'function';
    return isObj || isFunc ? res : obj;
}       
Copy the code

test

/ / verification
function Car(make, model, year) {
    this.make = make;
    this.model = model;
    this.year = year;
}
const car1 = new Car('Eagle'.'Talon TSi'.1993);
const car2 = myNew(Car, 'Kitty'.'TSi'.1997);
        
console.log(car1);
console.log(car2);
Copy the code

Shallow copy and deep copy

1. The shallow copy

What is shallow copy?

Create a new object and copy the original object property values in full. This includes the value of the original type and the memory address of the reference type.

Common shallow copy methods

Slice () : the slice() method returns a new Array object that is a shallow copy of the Array determined by begin and end (begin, end). The original array will not be changed. Usage:

const animals = ['ant'.'bison'.'camel'.'duck'.'elephant'];
var result = animals.slice();
Copy the code

(2) array.prototype. concat() concat is used to merge arrays, but can also be used for shallow copies. The MDN: concat() method is used to merge two or more arrays. This method does not change an existing array, but returns a new array.

The object.assign () method is used to assign the values of all enumerable attributes from one or more source objects to target objects. It will return the target object.

const target = { a: 1.b: 2 };
const source = { b: 4.c: 5 };

const returnedTarget = Object.assign(target, source);
console.log(target);// expected output: Object { a: 1, b: 4, c: 5 }
console.log(returnedTarget);// expected output: Object { a: 1, b: 4, c: 5 }
Copy the code

Note that it is a shallow copy, and the property values are copied, not the object itself.

let obj1 = { a: 0 , b: { c: 0}};
let obj2 = Object.assign({}, obj1);
console.log(obj2); //Object { a: 0, b: Object { c: 0 } }  

obj2.b.c = 1;
console.log(obj1); //Object { a: 0, b: Object { c: 1 } }
console.log(obj2); //Object { a: 0, b: Object { c: 1 } } 
Copy the code

(4) the ES6… Args (spread operator) The spread operator is three points (…) . Converts an array to a comma-separated sequence of arguments.

let arr = [1.2.3];
let newArr = [...arr];// The same effect as arr.slice()
console.log(newArr) //Array [1, 2, 3]
Copy the code

Implement shallow copy manually

var shallowClone = (target) = >{
    if (typeof target === 'object'&& target ! = =null) {const cloneTarget = Array.isArray(target)? [] : {};for (let prop in target){
            if(target.hasOwnProperty(prop)){
                cloneTarget[prop]=target[prop]
            }
        }
        return cloneTarget;
    }else{
       returntarget; }}Copy the code

2. Deep copy

One sentence deep copy implementation

JSON.parse(JSON.stringify()); The: json.parse () method in MDN is used to parse JSON strings and construct JavaScript values or objects described by the strings. The json.stringify () method converts a JavaScript object or value to a JSON string, optionally replacing the value if a replacer function is specified, or optionally containing only the properties specified by the array if the specified replacer is an array.

Handwritten implementation

The simple version

var deepClone = (target) = > {
    if (typeof target === 'object'&& target ! = =null) {
        const cloneTarget = Array.isArray ? [] : {};
        for (let prop in target) {
            if(target.hasOwnProperty(prop)) { cloneTarget[prop] = deepClone(target[prop]); }}return cloneTarget;
    } else {
        returntarget; }}Copy the code

Solve the circular reference problem

var deepClone=(target,map=new Map(a)) = >{
    if (map.get(target)){
        return target;
    }
    if (typeof target === 'object'&& target! = =null){
        map.set(target,true);
        const cloneTarget=Array.isArray(target)? [] : {};for (let prop in target){
            if(target.hasOwnProperty(prop)){
            // Whether it is its own property, rather than an inherited property, etccloneTarget[prop]=deepClone(target[prop],map); }}return cloneTarget;
    }else{
        returntarget; }}Copy the code

Three. Throttling and shaking prevention

  1. Image stabilization

The callback is executed n seconds after the event is triggered. If the event is triggered n seconds later, the timer is reset. Application scenarios: (1) Search (2) Window (resize

/ / image stabilization
// The event is triggered n seconds before the callback is executed. If it is triggered again within n seconds, the timer is reset.
// application scenarios :(1) click on the request to avoid sending multiple requests to the back end. (2) adjust the browser size
const debounce = (fn,time) = > {
    let timeout=null;
    return function(){
        if(timeout) {
            clearTimeout(timeout); 
            timeout = null
        }
        timeout = setTimeout (() = >{
            fn.apply(this.arguments);
        },time)
    }
 }
Copy the code
  1. The throttle

Only one function can be fired in a unit of event, and only one function can be fired in that unit of time. Application scenarios: (1) Repeatedly clicking the mouse triggers (2) Monitoring rolling events

/ / throttling
// Specify a unit of time within which only one trigger callback can be executed. If an event is triggered multiple times in the same unit of time, only one event takes effect
// application scenarios :(1) scroll function (2) input box input
const throttle = (fn,time) = > {
    let flag = true;
    return function(){
        if(! flag)return;
        flag = false;
        setTimeout(() = >{
            fn.apply(this.arguments);
            flag = true;
        },time)
    }
}
Copy the code

4. The asynchronous

1.Promise

Reference es6.ruanyifeng.com/#docs/promi… (1). What is the Promise ->Pomise holds the result of an event that will end in the future. A Promise is an object from which to get messages for asynchronous operations. This is a big pity. -> This is a pity. I Promise in three states: Pending, fulfilled, and rejected. Once the state has changed, it will never change again. (2) Basic usage ->resolve, which is called when an asynchronous operation succeeds and passes the result of the asynchronous operation as an argument. The reject function, which is called when an asynchronous operation fails and passes the error reported by the asynchronous operation as an argument. -> Order of execution: Promise is executed immediately, but the callback specified by the then method will not be executed until all synchronization tasks in the current script have been executed. Example:

let promise = new Promise(function(resolve, reject) {
  console.log('Promise');
  resolve();
});

promise.then(function() {
  console.log('resolved.');
});

console.log('Hi! ');

// Promise
// Hi!
// resolved
Copy the code

(3) Promise.prototype.then() adds a callback function to the Promise instance when the state changes. Returns: a new Promise instance. So we can use the chain notation. If there are two callback functions, the first callback completes and passes the result as an argument to the second callback function. (4) Promise. Prototype. Finally finally () method of the callback function does not accept any parameters, this means that there’s no way to know, the Promise in front of the state is fulfilled or rejected. This suggests that operations in the finally method should be state independent and not depend on the result of a Promise’s execution. (5) Promise.prototype.all() method: used to wrap multiple Promise instances into a new Promise instance. (6)Promise.protitype.race() Promise.race() also wraps multiple Promise instances into a new Promise instance.

Promise solution

(Reference: juejin.cn/post/684490… Promise solves callback hell with three techniques. (1) callback function delay binding (callback function is passed in later THEN method) (2) return value penetration (create different types of promises based on the incoming value of the then callback function, and then pass the returned Promise through the outer layer for subsequent calls). (3) Error bubbling (errors will continue to be passed backwards and will be received by catch, so there is no need to check errors frequently)

Promise to realize

  • Code implementation:

5. Event flow

1. Event capture and bubbling

(1) THE interaction between HTML and JS is realized by event-driven. (2) Three stages of event flow: event capture, target stage, event bubbling event capture: from outside to inside. Events bubbling: From the inside out. It is received initially by the most concrete element and propagated up the hierarchy to the topmost DOM node.

AddEventListner note: certain events without bubble: onblur, an onfocus, onmouseenter, onmouseleave

2. Event objects

event

div.onclick = function(event){}
div.addEventListener('click'.function(event){})
//1. Event is an event object written to the listener (in parentheses, as parameters).
//2. The event object will exist only when there is an event, which is automatically created by the system without passing parameters.
//3. Event object: a collection of data related to an event. Related to the event. (e.g. mouse click: contains mouse-related information, such as coordinates)
/ / 4. Compatibility: event = event | | document. The event
Copy the code

3. Common properties and methods of event objects

(1) event.target: Returns the object that triggered the event. (Compatibility: event.srcElement) The difference between target and this: Target refers to the object (element) that triggered the event, and this refers to the object (element) that bound the event.

<! -- -- -- > layout<ul>
    <li>li1</li>
    <li>li2</li>
    <li>li3</li>
</ul><! - events -- -- ><script>
    var ul = document.querySelector('ul');
    ul.addEventListener('click'.function(event){
        console.log(this);
        console.log(event.target);
    })
</script>
Copy the code

Execution Result:

4. Prevent events

PreventDefault behavior: event.preventdefault () prevents default behavior events such as links not jumping, buttons not submitting, etc. To prevent a bubble: the event stopPropagation () : compatibility (IE678: window. Event. CancelBubble () example: under normal circumstances:

<div class="father">
    <div class="son">sonson</div></div> <! - events -- -- ><script>
    var son = document.querySelector('.son');
    son.addEventListener('click'.function(){
        console.log('son');
    },false);

    var father = document.querySelector('.father');
    father.addEventListener('click'.function(){
        console.log('father');
    },false);

    document.addEventListener('click'.function(){
        console.log('document');
    },false);       
</script>
Copy the code

Routine results:

After adding the resistance bubble event, add stopPropagation() in son.

var son = document.querySelector('.son');
    son.addEventListener('click'.function(){
        console.log('son');
        stopPropagation();
    },false);
Copy the code

Results:

5. Event delegation

How it works: Instead of setting event listeners for each child node, place event listeners on its parent node and then use the bubbling principle to influence each child node. (Example: in the above example, register the click event for UL and use the target of the event object to find the current click on Li, because the event will bubble up to UL and UL will trigger the event listener if it registers the event.) Function: Only operate the DOM once to improve the performance of the program. Example:

<! -- -- -- > layout<ul>
    <li>li1</li>
    <li>li2</li>
    <li>li3</li>
    <li>li4</li>
    <li>li5</li>
</ul><! - events -- -- ><script>
// The core of event delegation: add listeners to the parent node, and use event bubbling to affect each child node
    var ul = document.querySelector('ul');
    ul.addEventListener('click'.function(event){
    // e.target gets our click object
        console.log(event.target.innerHTML);
    })
</script>
Copy the code

Vi. Variable/function promotion

1. Variable declaration enhancement: Use var to define (declare) variables and make them accessible before the statement is defined. Undefined 2. Function declaration improves the function declared by function and can be called directly before. Value: function definition (object) function promotion over variable promotion 3. Reason: Because JS is preprocessed first: a lexical environment is created, functions and variables declared in JS lifeforms are scanned and added to the lexical environment in the preprocessing stage.

An Event Loop

(Picture reference and the following article some reference content:Segmentfault.com/a/119000001…

Some concepts in the event loop:

SetTimeout, setInterval, setImmediate Mediate (IE10), I/O, UI Rendering, etc. 2. Microtasks process. nextTick (Node only), Promise, Object.observe(deprecated), MutationObserver.

Execution order

1. At the beginning, the whole script is executed as the first macro task. 2. 3. After the current macro task is executed, check the microtask queue. If there are any microtask queues, execute them one by one until the microtask queue is empty. 5. Check if there are Web worker tasks, and execute them if there are. Execute the new macro task at the head of the queue, return to 2, and repeat until both the macro and microtask queues are empty

(Reference: juejin.cn/post/684490…

test

console.log(1);

setTimeout(() = > {
  console.log(2);
  Promise.resolve().then(() = > {
    console.log(3)}); });new Promise((resolve, reject) = > {
  console.log(4)
  resolve(5)
}).then((data) = > {
  console.log(data);
  
  Promise.resolve().then(() = > {
    console.log(6)
  }).then(() = > {
    console.log(7)
    
    setTimeout(() = > {
      console.log(8)},0);
  });
})

setTimeout(() = > {
  console.log(9);
})

console.log(10);
,4,10,5,6,7,2,3,9,8 / / result: 1
Copy the code

New ES6 features

1.let

Let actually adds block-level scope to JS. (1) The let declaration variable is valid only in the code block where the let command is located. Common distinctions between let and var:

var a = [];
for (var i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6] ();/ / 10
Copy the code

In the above code, variable I is declared by var command, which is valid globally, so there is only one variable I globally. The value of variable I changes each time through the loop, and the console.log(I) inside the function assigned to array A refers to the global I. That is, all the I’s in array A refer to the same I, causing the runtime to print the value of the last round of I, which is 10. After using let:

var a = [];
for (let i = 0; i < 10; i++) {
  a[i] = function () {
    console.log(i);
  };
}
a[6] ();/ / 6
Copy the code

In the above code, the variable I is declared by let, and the current I is only valid for this loop, so each loop I is actually a new variable, so the final output is 6. You might ask, if the variable I for each cycle is redeclared, how does it know the value of the previous cycle and thus calculate the value of the current cycle? This is because the JavaScript engine internally remembers the value of the previous cycle, and when it initializes the variable I of this cycle, it evaluates on the basis of the previous cycle. (2) There is no variable promotion in let. (3) There is a temporary dead zone in let, that is, the variable is unavailable within the code block until it is declared by the let command.

var tmp = 123;
if (true) {
  tmp = 'abc'; // ReferenceError is not ok even if there are global variables in front of it
  let tmp;
}
Copy the code

2.const

Const declares a read-only constant that, once declared, cannot be changed, must be initialized immediately. Const scope is valid only in the block-level scope of the declaration (same as let)

3.Symbol

Introduce essence: Prevent object property name conflicts. Symbol can be explicitly converted to the string sym.tostring () // ‘Symbol(My Symbol)’. It can also be converted to a Boolean value (but not to a number). Prevents a key from accidentally being overwritten or overwritten. (for example in the re-call above this article)

let mySymbol = Symbol(a);let a = {};
a[mySymbol] = 'Hello! ';
Copy the code

4. The Set () and Map ()

1.Set() ES6 provides a new data structure called Set. It is similar to an array, but the values of the members are unique and there are no duplicate values. Set() can add members to a Set structure using the add () method, or it can take an array (or some other data structure with an Iterable interface) as an argument to initialize. There is no type conversion when a Set is added to a value (similar to ===,5 and “5” are considered unequal. The difference is that NaN can only be added once multiple times.)

const set = new Set([1.2.3.4.4]);
[...set] // [1, 2, 3, 4]
Copy the code

2. A collection of Map() key-value pairs. You can also take an array (or any data structure with an Iterator interface where each member is a two-element) as an argument

What is the difference between a Set and a Map? A Map is a Set of key-value pairs, and a Set is a Set of keys (no values are stored). There are no duplicate keys in a Set.

5.for… of…

A data structure that deploys the Symbol. Iterator attribute is considered to have an iterator interface. The of loop iterates through its members. That is to say, for… Inside the of loop is the symbol. iterator method of the data structure. for… The scope of the of loop includes arrays, Set and Map structures, some array-like objects (such as Arguments objects, DOM NodeList objects), Generator objects, and strings.

Arrow function

(1) The arrow function has no this value. The this value in this function depends on the this value of the outer function. (2) can’t use constructor, no prototype value, no arguments.

Other frequently tested front-end content

A cross domain

Ii. Code design patterns

3. Browser cache policy

1. www.jianshu.com/p/7531c98a6…