I. call
call has two wonderful functions
1. Inheritance (I mentioned in the previous article that call is used to implement call inheritance. If you are interested, you can read it. https://www.cnblogs.com/pengshengguang/p/10547624.html)
2. Modify the direction of this when the function is running (to be said today)
// Code segment 1
var obj = {name: 'psg'};
function fn(num1, num2) {
console.log(num1+num2);
console.log(this)
}
// 1. In the call, the first parameter will say the object to be this
fn(100, 200); //this points to window, num1=100, num2=200
fn.call(100, 200); //this points to 100, num1=200, num2=undefined
fn.call(obj, 100, 200); //this points to obj, num1 = 100, num2 = 200
// 2. In non strict mode, if the first parameter in call is empty, null, undefined, this will point to window.
fn.call(); //this points to window
// 3. In the strict mode, in the call, the person who transmits this is the person who does not transmit this is defined.
fn.call(); //this points to undefined
fn.call(null); //this points to null
fn.call(undefined); //this points to undefined
Two, apply
1, the functions of apply and call are exactly the same, they are used to change the this keyword in the method and execute the method, and in the strict mode and non strict mode, the same rule is also true for the first parameter is null / undefined.
2. The only difference between call and call is the syntax:
//call passing parameters are separated by commas and passed in one by one
fn.call(obj, arg1,arg2,arg3.....)
//The parameter passed by apply is passed by an array
fn.apply(obj, [arg1,arg2,arg3....])
Three, bind
1. This method is not compatible under IE6-IE8.
2. Similar to apply and call, they are used to change the direction of this, but bind embodies the preprocessing idea of js.
Preprocessing: to change this of fn to the desired result, and to prepare the parameters of the object, which will be used in the future, just execute directly.
var obj = {name: 'psg'};
function fn(num1, num2) {
console.log(num1+num2);
console.log(this);
}
fn.call(obj, 100, 200);
fn.bind(obj, 100, 200); // It only changed this in FN to obj, and passed two parameter values to FN, but it did not execute the function fn at this time.
// However, there will be a return value when bind is executed. This return value myFn is the result after we change this of fn!!!
//So, how to make fn function execute? The following writing method can solve the problem
var myFn = fn.bind(obj, 100, 200);
myFn();
IV. in depth understanding of call
4.1 if we want to understand the call, we should first know how the call is executed, involving the prototype chain search mechanism.
//For example, now there is a function fn. We want to change the direction of this in FN, so we can
fn.call(obj);
//The above code, in fact, first finds the call method in function.ptotype through the prototype chain of fnl, and then executes the call method. this in cal method is fn.
4.2 pseudo code simulation implementation call method
Function.prototype.myCall = function(context) {
//->1. Change this keyword in fn to context
this = eval(this.toString().replace("this", context));
//->2. Let fn execute
this();
}
4.3 classic interview questions
// Exercise 1
function fn1() {console.log(1);}
function fn2() {console.log(2);}
fn1.call(fn2); // ->1
//Principle: first, fn1 finds the call method on Function.prototype through prototype chain mechanism, and makes the call method execute
// At this time, this in the call method is fn1. During the execution of the call method, change this keyword in fn1 to fn2, and then let fn1 execute.
fn1.call.call(fn2); // ->2
//First, fn1 finds the call method on Function.prototype through prototype chain mechanism, and then lets the call method find the call method through prototype.
// Call on Function.prototype prototype (because fn.call is also a function data type). When the call is found the second time, let the call method execute. At this time
// this is fn1.call.
end