1.this point
- Function has three execution modes: global function, object method and constructor
- this: I point to whoever calls me (independent of the function declaration, depending on the function call)
- Global function: function name () -------------- > this points to window
- Object method: object name Method name () ---- -- > this points to the object
- Constructor: new function name () ------------- > this points to the empty object created by new
Analysis of this pointing experience: this pointing depends on the function call, and the function has three calling methods. So there are three situations when this points
(1) The exclusion method is preferred. If there is a new keyword, it points to the object created by new. Otherwise, it is either a window or an object
(2) How to judge whether this is a window or an object depends on whether the call is a function name () or an object name Method name ()
let obj = { name: 'ikun', sayHi: function () { function fn() { console.log(this); } fn()// Ordinary function call: the function name () fn calls this, so this points to window } } obj.sayHi()//window
let obj1 = { name: 'ikun', sayHi: function () { console.log(this); } } obj1.sayHi() //Object method call: object name Method name () object obj1 called this, so this points to obj1 object
function Fn() { console.log(this); } new Fn()//Constructor call: new function name () executes the process according to new / creates an empty object - this points to this object - object assignment - returns the object, where this points to the empty object created by new
Common feature: the direction of this cannot be dynamically modified
2. Function context execution mode (call/apply/bind)
2.1 context mode considerations
- a. The Function context has three methods: call() apply() bind(), which are defined in the prototype of the Function constructor
- b. If you change this point to the value type: (number,boolean,string), the function will automatically wrap it into the corresponding reference type (basic wrapper type)
- Value type: '123',1,true
- Basic packing type: String('123'),Number(1),Boolean(true)
2.2 function context function:
this point in the function can be dynamically modified
2.3 similarities and differences:
- The same thing: you can modify the point of this in the function
- difference:
1. Different parameter transfer methods: call refers to one-to-one parameter transfer, and apply refers to array / pseudo array parameter transfer
2. Different execution mechanisms: call and apply will execute the function immediately, while bind will not execute the function immediately
2.3 syntax
There are three ways to write. The functions are the same. Change this and the application scenarios are different
- call() syntax: function name call(this modified point, parameter 1, parameter 2,...)-------------- Applicable to function parameter < = 1
- apply() syntax: function name apply(this modified point, pseudo array or array) ----------------- applicable to the original parameter of the function > = 2
- bind() syntax: function name bind(this modified point)
The bind() syntax does not execute the function immediately, but returns a new function after modification, which is often used in callback functions
If the parameter is passed during bind, the parameter will also be bound, and the argument cannot be passed later
<script> /* 1.Functions can be executed in three ways: Global function: this points to window Object method: this points to the object Constructor: this points to the object created by new Common feature: the direction of this cannot be dynamically modified 2.Function context mode: 2.1 Function: you can dynamically modify this in the function 2.2 Syntax: there are three ways of writing. The functions are the same. Change this and the application scenarios are different a. Function name Call (modified this,arg1,arg2.............) * Applicable to function parameter < = 1 b. Function name Apply (modified this, [array or pseudo array]) * Applicable to function parameter > = 2 c. Function name Bind (modified this,arg1,arg2.............) * Features: this function will not be executed immediately, but will return the new function after modifying this * Applicable to functions that will not be executed immediately: event handling function, timer function */ // function fn(){ // //The three execution modes this cannot be dynamically modified // //this = {age:18}; // console.log(this); // }; // fn();//this:window /* Context mode */ function fn(a, b) { console.log(this); console.log(a + b); }; //a. Function name Call (modified this,arg1,arg2.............) //Application scenario: applicable to function original parameter < = 1 fn(10, 20);//this:window 30 fn.call({ age: 18 }, 100, 200); //age:18 300 //b. Function name Apply (modified this, [array or pseudo array]) //Application scenario: applicable to function parameter > = 2 fn.apply({ age: 88 }, [20, 30]); //c. Function name Bind (modified this) //Features: this function will not execute immediately, but return a new function after modifying this //Application scenario: event handling function, timer let newFn = fn.bind({ name: 'Hyk ' }); console.log(newFn); newFn(50, 60); //4. this in the timer must point to window // Timer: a piece of code interval event execution setTimeout (a piece of code, interval time) //4.1 named function let test = function () { console.log('I'm a named function'); console.log(this); }; let newTest = test.bind({ name: 'Zhang San' }) setTimeout(newTest, 3000); //4.2 anonymous functions setTimeout(function () { console.log('I am a function in the timer'); console.log(this); }.bind({ name: 'Li Si' }), 2000); </script>
Function call() application scenario
/* 1. Function up and down execution mode: dynamically modify this Note: the modified this can only be a reference type 2.If the basic data type is written string,number,boolean : Customize and help us convert to the corresponding basic package type new String() Boolean() Number() undefined,null : */ function fn() { console.log(this); }; fn.call('str');//String fn.call(1);//Number fn.call(true);//Boolean //If undefined and null are passed, or not. The code will not report an error, nor will it help us modify this. It is still the original window fn.call(undefined);//Window fn.call(null);//Window fn.call();//Window fn.call(window);//Window
Object.prototype.toString.call() universal test data type
1.Object.prototype.toString() gets a fixed format string
2. Fixed format syntax of detection data type: object prototype. toString. call()
Get a fixed format string: [object data type]
/* call Scenario: data type detection */ //1. typeof data: detection data type /* typeof Two data types cannot be detected: null and array will get object */ console.log( typeof '123' )// 'string' console.log( typeof 123 )//'number' console.log( typeof true )//'boolean' console.log( typeof undefined )//'undefined' console.log( typeof null )//'object' console.log( typeof [10,20,30] )//'object' console.log( typeof function(){} )//'function' console.log( typeof {name:'123'} )//'object' //2. Object.prototype.toString(): get fixed format string //"[object type]", where type is the type of the object //Detect fixed format syntax of data type: object prototype. toString. Call (data) console.log( Object.prototype.toString.call('123') )//[object String] console.log( Object.prototype.toString.call(123) )//[object Number] console.log( Object.prototype.toString.call(true) )//[object Boolean] console.log( Object.prototype.toString.call(undefined) )//[object Undefined] console.log( Object.prototype.toString.call(null) )//[object Null] console.log( Object.prototype.toString.call([10,20,30]) )//[object Array] console.log( Object.prototype.toString.call(function(){}) )//[object Function] console.log( Object.prototype.toString.call({name:'123'}) )//[object Object]
apply context call
function fn(a,b){ console.log(this) console.log(a+b) } fn(1,2)//Common function this - > window //(1) Function name Call (modified this, parameter 1, parameter 2,...) fn.call({name:'Zhang San'},10,20) //(2) Function name Apply (modified this, array / pseudo array) //When apply ing passes parameters, it will automatically traverse the array, and then pass parameters a = [30,40][0] b=[30,40][1] one by one in sequence fn.apply({name:'Li Si'},[30,40]) </script>
arr.push. Application scenario of apply (arr, pseudo array): pseudo array to true array
<script> /* Pseudo array: there are three elements of an array (subscript, element and length), but the array method cannot be used Pseudo arrays are essentially objects Pseudo arrays cannot use Array methods: the prototype of a pseudo Array points to the prototype of an object, not the prototype of an Array */ let obj = { 0: 10, 1: 20, 2: 30, 3: 40, length: 4,//length cannot be omitted } console.log(obj[0]); //Convert the pseudo array to the real array arr.push, add elements to the back of the array, and return the length of the array let newArr = [] let a = newArr.push(obj[0], obj[1], obj[2], obj[3]) console.log(newArr)//[10, 20, 30, 40] console.log(a)//Array length 4 // ES5: Context let newArr1 = [] newArr1.push.apply(newArr1, obj) //The first parameter: newArr1. Originally, this is newArr. There is no need to modify this (equivalent to this unchanged) //The second parameter: obj with the help of the apply feature: automatically traverse the pseudo array / array and pass the parameters one by one (omitting the for loop) console.log(newArr1); // ES6 recommendation: arr.from (pseudo array) pseudo array to real array let arr = Array.from(obj) console.log(arr); </script>
Math.max.apply(Math, arr) application scenario: find the maximum value of the array
<script> //Max array let arr = [10, 13, 12, 3, 14, 23, 32] // 1.arr.sort() array sorting parameter: callback function fixed syntax rote // arr.sort(function (a, b) { // return a - b / / from small to large // return b - a / / sort from large to small // }) arr.sort(function (a, b) { return b - a }) console.log(arr[0]); //2. Challenge arena thought let max = 0 for (let i = 0; i < arr.length; i++) { if (arr[i] > max) { max = arr[i] } } console.log(max) // ES5: Math.max.apply(Math, array name) //Function name Apply (modified this, array / pseudo array) //The first parameter Math: Math calls the method. This refers to math. There is no need to modify this (pass math, equivalent to this unchanged) //The second parameter arr: with the help of the characteristics of apply Automatically traverse the array / pseudo array and pass parameters one by one let max3 = Math.max.apply(Math, arr) console.log(max3); //ES6 (recommended): let max4 = Math.max(...arr) console.log(max4) </script>
bind context call
function fn(a,b){ console.log(this) console.log(a+b) } fn(1,2)//Common function this - > window //(1) Function name Call (modified this, parameter 1, parameter 2,...) fn.call({name:'Zhang San'},10,20) //(2) Function name Apply (modified this, array / pseudo array) //When apply ing passes parameters, it will automatically traverse the array, and then pass parameters a = [30,40][0] b=[30,40][1] one by one in sequence fn.apply({name:'Li Si'},[30,40]) //(3) Function name Bind (modify this) //bind does not call the function immediately, but gets a new function after modifying this let newFn = fn.bind({name:'Wang Wu'}) newFn(25,66)
bind() application scenario
The bind scenario is mainly used to modify functions that do not need to be executed immediately
//Event handling function, timer function
//The bind scenario is mainly to modify 'functions that do not need to be executed immediately' // Event handling function, timer function //1. this in the timer must be window let fn = function(){ console.log( this ) } //Modify this using bind let newFn = fn.bind({name:'666'}) // fn(): call the function, and the result is the return value of the function // fn: value of the variable, and fetch the heap address stored in fn setTimeout( newFn ,3000) //The following is the same as the above: functions are data types, and syntax can be used directly like other data setTimeout(function(){ console.log(this) }.bind({name:'Dry rice'}),3000)
3. Recursive function:
/*Higher order functions: self calling function, callback function, closure, recursion*/
What is a recursive function?: Function calls itself internally
*Note: you need to meet the conditions before recursion, otherwise it will lead to an endless loop
*Recursive functions are similar to loop functions
//A function recursion // function fn(){ // console.log('ha ha '); // fn(); // }; // fn(); //Two function recursion // function fn1(){ // console.log('ha ha '); // fn2(); // }; // function fn2(){ // console.log('ha ha '); // fn1(); // }; // fn2(); //Requirements: write a function and print the monitor AI Kunge three times let i = 1; function fn(){ console.log('study hard'); i++; if(i <= 3){ fn(); }; //Loop implementation // for(let i = 1;i<=3;i++){ // console.log('monitor AI Kun '); // }; }; fn();
Recursive application scenario:
2.1 light copy and deep copy
1. Shallow copy: the address is copied, and the modified copied data has an impact on the original data
//Declare an object //Copy: copy a copy of the data stored in the object and assign it to other objects let obj = { name:'ikun', age:30, hobby:['lecture','student','study'], friend:{ name:'friend', sex:'male' } } //Shallow copy: the copy is the address let obj1 = obj //Due to shallow copy, the copy is the address. Therefore, after modifying the copied data, the original data will also change obj1.hobby = 'delicious food' console.log(obj1,obj)
2. Deep copy: data is copied, and the modified copied data has no impact on the original data
let obj = { name:'ikun', age:30, hobby:['lecture','student','study'], friend:{ name:'friend', sex:'male' } } /* (1)Traverse obj and add all attributes to newObj (2)If obj[key] is a reference type (array, object), the address cannot be copied directly (2.1)Array: declare an empty array for newObj, then traverse obj[key], and add the elements inside to newObj[key] (2.2)Object: declare an empty object for newObj, then traverse obj[key], and add the inner elements to newObj[key] (3)If obj[key] is not a reference type, it is assigned directly. End recursion */ function kaobei(newObj,obj){ for(let key in obj){ //Determine whether obj[key] is an array type if( obj[key] instanceof Array ){ //Declare an empty array and continue copying the data in the array newObj[key] = [] kaobei(newObj[key],obj[key]) }else if(obj[key] instanceof Object){ //Declare an empty object and continue copying the data in the array newObj[key] = {} kaobei(newObj[key],obj[key]) }else{ newObj[key] = obj[key] } } } //Call the deep copy function let newObj = {} kaobei(newObj,obj) //Deep copy: modifying the copied data has no impact on the original data newObj.hobby[0] = '111' console.log( newObj,obj)
3. Realize deep copy with JSON conversion
/* 2.Deep copy can be implemented in two ways 2.1 Recommended: json conversion 2.2 Recursion: */ let obj = { name:'ikun', age:30, hobby:['lecture','student','study'], friend:{ name:'friend', sex:'male' } } //(1) First, convert the js object into a json format string: json Stringify (js object) //When json converts js into json format string, the bottom layer will automatically copy it for you // let json = JSON.stringify(obj) // console.log( json ) //(2) Then convert the json string just now into a js object: json Parse (json format) // let js = JSON.parse( json ) // js.hobby = 'learning' // console.log( js,obj ) //The above two processes can be simplified into one line of code let newObj = JSON.parse( JSON.stringify( obj ) ) newObj.friend = 'puppy' console.log(newObj,obj)
4. Traverse the dom tree
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <meta http-equiv="X-UA-Compatible" content="ie=edge" /> <title>Document</title> <style> * { padding: 0; margin: 0; } .menu p { width: 100px; border: 3px solid; margin: 5px; } .menu > div p { margin-left: 10px; border-color: red; } .menu > div > div p { margin-left: 20px; border-color: green; } .menu > div > div > div p { margin-left: 30px; border-color: yellow; } </style> </head> <body> <div class="menu"> <!-- <div> <p>First level menu</p> <div> <p>Second level menu</p> <div> <p>Third level menu</p> </div> </div> </div> --> </div> <script> //The server returns an indeterminate data structure involving multiple array nesting let arr = [ { type: 'electronic product', data: [ { type: 'mobile phone', data: ['iPhone mobile phone', 'Mi phones', 'Huawei mobile phone'] }, { type: 'Flat', data: ['iPad', 'Flat millet', 'Tablet Huawei'] }, { type: 'Intelligent Watch', data: [] } ] }, { type: 'Living home', data: [ { type: 'sofa', data: ['Leather sofa', 'Cloth sofa'] }, { type: 'chair', data: ['Dining chair', 'Computer chair', 'Office chair', 'Leisure chair'] }, { type: 'Table', data: ['desk'] } ] }, { type: 'snacks', data: [ { type: 'Fruits', data: [] }, { type: 'Coffee', data: ['Nescafe'] } ] } ] //arr: Data father: parent box function addElement(arr,father){ //Traverse the array, generate div > P and add it to the parent element for(let i = 0;i<arr.length;i++){ //(1) Create empty label let div = document.createElement('div') //(2) Set content div.innerHTML = `<p>${arr[i].type || arr[i]}</p>` //(3) Add to parent box father.appendChild(div) //If the menu still has data, it indicates that there are submenus, you need to continue to traverse and add if( arr[i].data ){ addElement(arr[i].data,div) } } } let menu = document.querySelector('.menu') //Call function addElement(arr,menu) </script> </body> </html>
4. Closure:
- 1. What is a closure: a closure is a function that can access internal variables of other functions
- 2. The function of closure: solving variable pollution
function fn(){ let a = 1 //In the fn1 function, variables inside other functions fn are accessed. fn1 + a form closure function fn1(){ console.log(a) } fn1() } fn() function test(){ let num = 1 setTimeout( function(){ console.log(num) },2000) } test()
Closure scenario:
<script> /* 1.What is a closure? 1.1 A closure is a function that accesses internal variables of other functions 1.2 Closure = combination of function + context reference Conclusion: there are two conditions for the formation of closures, one of which is indispensable. (1) Function (2) accessing internal variables of other functions 2.Closure effect: variable pollution * Most of the late closures are usually in the callback function */ //Get element let input = document.querySelector('input') let button = document.querySelector('button') button.onclick = function(){ //There is a variable to store search results let str = '6666' //Simulate network request: get search results after 2 seconds setTimeout(function(){ alert(`The search is over. The search result is ${str}`) },2000) } </script>
5. Summary:
5.1 three directions of this
- Global function: function name () -------------- > this points to window
- Object method: object name Method name () ---- -- > this points to the object
- Constructor: new function name () ------------- > this points to the empty object created by new
5.2call, apply and bind differences
- The same point: both modify the function this point
- difference
- The parameter transfer methods are different: call is used for a single parameter and apply is used for multiple parameters
- The execution mechanism is different: call and apply will be executed immediately, and bind will not be executed immediately
- call and apply are modified once
- bind; Once modified, it is valid for life
5.3 closure
- What is a closure: both of the following answers are OK
- A closure is a function that accesses internal variables of other functions
- Closures are function + context code combinations
- Closure function: solving variable pollution
5.4 recursion
- What is recursion: a function calls itself internally
- Recursive scenario
- Deep copy
- Traversing dom tree