Note: The case environment of this paper is non-strict mode, in which the keyword this is prohibited to point to global objects

How is the method implemented?

Declare a method a under the global window:

function a () {
  console.log(this);
}
a();//window
Copy the code

The common way to execute this globally is directly a(), which is executed in the window environment, and the console prints out the Window object.

So why is the window object printed out? Method a is defined in the global context of the window. Variables and methods under the window can be accessed and called without the window. A () === window.a() = window.a(); !

The direct caller is mentioned above. What about the direct caller? For example, declare a global object obj:

var name = "window-name";
var obj = {
    name:"obj-name".a:function(){
        console.log(this.name);
    },
    b: {name:"b-name".a:function(){
            console.log(this.name);
        }
    }
}
obj.a();//obj-name
obj.b.a();//b-name
Copy the code

Obj.a (); And obj. B.a (); Obj.a () === window.obj.a() === window.obj.b.a() === window.obj.b.a()) Obj and obj.b, respectively, print the name of obj and obj.b, respectively.

2. Who does this refer to?

So who is this in this function? This is the direct caller when the method is called. Let’s do a special example, and if we understand this example we’ll have a good idea who this refers to. Define a global variable based on what we just did:

var ax = obj.b.a;
ax();//window-name
Copy the code

Execute ax(); The console prints window-name; Why is window-name printed? Ax () === window.ax()); ax() === window.ax()); So the printed value is the value of name defined under window, so a() at the beginning of this article prints window because the internal this refers to the caller of A, Window.

In fact, in non-strict mode, this points to a direct caller if the method has one, and to a global object (Window in the browser, global in Node) if there is no direct caller (such as a callback function).

3. What have call and Apply changed?

Now that you understand the direct callers and this, call and apply are easier to understand. Without going into too much definition of call and apply, let’s look at which method is executed when call is called. Examples of direct code:

function fn1 () {
    console.log(1);
};
function fn2 () {
    console.log(2);
};
fn1.call(fn2);/ / 1
Copy the code

Perform fn1. Call (fn2); The console prints 1, which indicates that fn1 is still executing the call. It is important to know who is executing the call function, and fn2 is now the direct caller of fn1 instead of Window. This is key to understanding call and apply. You can also run fn2.call(fn1). //2 to verify which method is being executed. So what does call do? Here’s another code example:

var obj1 = {
    num : 20.fn : function(n){
        console.log(this.num+n); }};var obj2 = {
    num : 15.fn : function(n){
        console.log(this.num-n); }}; obj1.fn.call(obj2,10);/ / 25
Copy the code

Perform obj1. Fn. Call (obj2, 10); Num = this.num = obj2.num = this.num = this.num = this.num = obj2.num = this.num = this.num = this.num = this.num = this.num = obj2.num 10 is passed in as the argument when obj1.fn is executed, obj2.num is 15, so the printed value is 15+10=25.

The effect of call is to change the direct caller of the method being executed. The this inside the executed method also refers back to the new caller, which is the first obj argument received by the call method. There are also two special cases where this points to the window when the obj parameter is null or undefined.

4. The difference between call and apply

The call method takes a list of arguments as arguments to the method being executed in addition to the first obj argument. The use of apply is similar to the use of call, except that the second argument, in addition to the first obj argument, receives an array as arguments to the method being executed.

Fifth, extend and expand

Let’s execute the following code:

fn1.call.call(fn2);/ / 2
Copy the code

Perform fn1. Call. The call (fn2); The call() method is on the prototype chain of the Function object, so fn1 can use this method by inheriting from the prototype chain. Prototype call === function.call Call (fn2) === Function. Call. Call (fn2), FunCall (fn2) == Function.

FunCall.call(fn2);
Copy the code

This is equivalent to fn2 performing FunCall as a direct caller of FunCall, and FunCall === function.call, so it is equivalent to fn2.call().

Fn2.call (window); fn2.call(window); fn2 call(window); So it’s just fn2(); The console will print out 2.

Function. Call. apply and Function. Apply. call are all similar in principle, but receive different types of parameters. Deepen your understanding of call and apply.

6

The use of bind is similar to that of call, except that the bind method does not execute immediately and needs to be called again. Let’s implement a simple version of bind called bindFn to get a sense of what bind is:

Function.prototype.bindFn = function() {
    var args = Array.prototype.slice.call(arguments);// Get the parameters passed in
    var obj = args.shift();// Get the first object passed in
    var self = this; // Call bindFn's function
    
    return function() { // return a function that implements currie
        // Concatenate new parameters
        var newArgs = args.concat(Array.prototype.slice.call(arguments));
        // Here we use apply to change the direct caller of self
        returnself.apply(obj,newArgs); }}// The doSum method increments the parameters passed in and returns the sum
function doSum(){
    var arg = Array.prototype.slice.call(arguments);
    return arg.length ? arg.reduce((a,b) = > a + b) : "";
}
var newDoSum = doSum.bindFn(null.1.2.3);
console.log(newDoSum());/ / 6
console.log(newDoSum(4));/ / 10
console.log(newDoSum(4.5));/ / 15
Copy the code