Mind mapping

A couple of things about THIS

  • DOM2 = THIS ->window; DOM2 = THIS ->window; DOM2 = THIS ->window
  • 2. Execute the method to see if there is a “dot” in front of the method, there is a “dot”, who is in front of the “dot”, THIS is who, no “dot”, THIS is a window, “In strict mode, there are undefiend and undefiend + THIS is a window/undefined + THIS is a window/undefined in the callback function .
  • 3. The constructor executes. THIS in the constructor body is an instance of the current class
  • 4. Arrow function does not have THIS “similar to block level context”, so no matter how to execute, how to modify, it is useless, if THIS occurs in the function, must be its parent context THIS
  • Function. Prototype provides three methods: call/apply/bind. These three methods are used to force this to change the reference of Function.

🌟 example

let obj = {
    name: 'zhufeng'.fn() {
        // this -> obj
      console.log(this);
        let self = this;
        setTimeout(function () {
            // This -> window
            console.log(this);
        }, 1000);
        setTimeout(() = > {
            console.log(this);
            // The arrow function this is in the parent context, i.e. obj
        }, 1000);
    }
}
obj.fn();
Copy the code

🌟 example

"use strict";
window.name = 'window';
const fn = function fn(x, y) {
    console.log(this, x + y);
};
let obj = {
    name: 'obj'
};
fn(); //this->undefined Uncaught TypeError: Cannot read property 'name' of undefined
obj.fn(); //Uncaught TypeError: obj. Fn is not a function Obj does not have fn attributes and is not associated with each other. An error is reported
Copy the code

Change the call/apply/bind method for THIS’

call

  • Requirement: Execute fn with this as obj and pass 10/20 to x and y parameters, respectively

This refers to fn (changing the value of this via the first argument), the first argument context->obj will change the reference to this in the function in the future, and the remaining arguments params->[10,20] store the arguments to be passed to the function in the future. Call method execution helps us to execute fn “this” and have this refer to obj “context”, passing 10/20 “params” to the function. By default, three parameters are passed: the first parameter is the object type, the second parameter is data one, and the third parameter is data two.

fn.call(obj, 10.20);
fn.call(); Object {name: "obj"} 30
fn.call(null/undefined); // this->window &null /undefined x=undefined y=undefined
fn.call(10.20); //this->10 x=20 y=undefined Number {10} NaN
Copy the code

apply

There is only one difference between apply and call. The call method sets the parameters to be passed to the function. However, apply requires the user to pass all the argument information as an array/class array. Only two parameters can be passed by Apply. The first parameter is the object type and the second parameter is the array (only the first two values in the array are valid). Although this is required, the internal final processing of apply, like call, is passed to the function item by item.

fn.apply(obj, [10.20]); // Call is better than apply
Copy the code

Application scenarios

🌟 Scenario 1: Find the maximum or minimum value of an array

let arr = [10.14.23.34.20.13];
// sort N^2 sort N^2
 console.log(arr.sort((a, b) = > b - a)[0]);

// 2
let max = arr[0],
    i = 1,
    len = arr.length,
    item;
for (; i < len; i++) {
    item = arr[i];
    if(item > max) { max = item; }}console.log(max); 

// 3.Math. Max get the maximum value recommended
console.log(Math.max(10.14.23.34.20.13)); / / = > 34
console.log(Math.max(arr)); //=> The NaN method itself gets the maximum value of a bunch of numbers, and you need to pass the number of comparison items to the Max method to pass an array of NaN output
// You want to pass each item in the array to the Max method separately
let max = Math.max(... arr);console.log(max); / / = > 34
max = Math.max.apply(null, arr); // Take advantage of apply's mechanism "although an array is passed to Apply, each item in the array is passed to the corresponding function by Apply"; And math. Max doesn't use this, so it doesn't matter who this is, just the ones place;
console.log(max); / / = > 34
Copy the code

🌟 Scenario 2: Sum of arbitrary numbers “Uncertain number of arguments, so cannot accept based on set parameters”

// + residual operator ES6
// + arguments ES3
const sum = function sum(. params) {
    if (params.length === 0) return 0;
    // params -> array
    return params.reduce((total, item) = > total + item, 0);
};

const sum = function sum() {
    let params = arguments; // params -> class array "can't use array method directly"
    if (params.length === 0) return 0;
    // Convert the class array to an array
    // + params = Array.from(params); ES6+
    // + params = [...params]; ES6+
    / / +...
    let i = 0,
        len = params.length,
        arr = [];
    for (; i < len; i++) {
        arr[arr.length] = params[i]; //<==> arr.push(params[i]);
    }
    return arr.reduce((total, item) = > total + item, 0);
};

Array.prototype.slice = function slice() {
    // The method of simulation
    // this -> ary
    let i = 0,
        len = this.length,
        arr = [];
    for (; i < len; i++) {
        arr[arr.length] = this[i];
    }
    return arr;
};
// ary.slice()
// ary.slice(0)
// // array clone, clone each item in the original array to the new array returned "shallow clone"

const sum = function sum() {
    let params = arguments;
    if (params.length === 0) return 0;
    If we can execute slice and let this in slice be arguments, then this is equivalent to iterating over each item in slice and assigning each item to a new array collection -> convert the array array to an array
    / / + how to make slice Array. The prototype. The slice () / []. Slice ()...
    // how to change this call/apply in slice...
    params = [].slice.call(params);
    / / principle: "Because of such arrays and the result of the very similar", so most of the operation of the array code, applies to class array, under this premise, we only need to implement good array method, method of this set to similar groups, in this operation is equivalent to a class array to write code, realize the purpose of such arrays use method, This operation is called "duck type."
    return params.reduce((total, item) = > total + item, 0);
};

 const sum = function sum() {
    let params = arguments;
    if (params.length === 0) return 0;
    // If you want to borrow it, you can borrow it
    return [].reduce.call(params, (total, item) = > total + item, 0);
};

 const sum = function sum() {
    let params = arguments;
    // params.__proto__ = Array.prototype; // Change the pointing arguments of the prototype chain directly using any method on the array prototype
    params.reduce = Array.prototype.reduce;
    if (params.length === 0) return 0;
    return params.reduce((total, item) = > total + item, 0);
};
console.log(sum()); / / - > 0
console.log(sum(10)); / / - > 10
console.log(sum(10.20)); / / - > 30
console.log(sum(10.20.30)); / / - > 60
Copy the code