To sum up: The orientation of this is determined at call time.

1. This of the global environment

function fn1(){
    console.log(this);
}

function fn2(){
    'use strict'
    console.log(this)
}

fn1(); // window
fn2(); // undefined
Copy the code

1. In non-strict mode, this refers to window.

2. In strict mode, this refers to undefined.

const fn = {
    bar: 10,
    bs: function(){
        console.log(this);
        console.log(this.bar);
    }
}
var f = fn.bs;
f();
// window 
// undefined
Copy the code

Here this still refers to the window. Because f is executed under the global environment window.

What if it were in the following form?

const fn = { bar: 10, bs: function(){ console.log(this); console.log(this.bar); } } fn.bs(); / / 10;Copy the code

Here this refers to the object that last called it. In the fn.bs() statement, this refers to the FN object.

If this is called by an upper-level object, then this refers to the upper-level object; otherwise, it refers to the global environment.

2. This is called in the context object

Const foo = {name: 'jun ', fn: function(){return this; }}; console.log(foo.fn() === foo); // trueCopy the code

When there is a complex nested relationship, this refers to the last object to call it.

Const foo = {name: 'qian jun ', obj:{name: 'Lucy', fn: function(){return this.name; } } } console.log(foo.obj.fn()); // LucyCopy the code

For a more advanced problem, see the following code run

const fn1 = {
    text: 'fn1',
    fn: function(){
        return this.text;
    }
}

const fn2 = {
    text: 'fn2',
    fn: function(){
        return fn1.fn();
    }
}

const fn3 = {
    text: 'fn3',
    fn: function(){
        var fns = fn1.fn
        return fns();
    }
}

console.log(fn1.fn()); // fn1
console.log(fn2.fn()); // fn1
console.log(fn3.fn()); // undefined
Copy the code

This of fn3.fn() points to the window.

So how to make fn2.fn() return fn2?

const fn1 = {
    text: 'fn1',
    fn: function(){
        return this.text;
    }
}
const fn2 = {
    text: 'fn2',
    fn: fn1.fn
}

console.log(fn2.fn());  // fn2
Copy the code

3. Bind, call, and apply to change this

Bind, call, and apply

To summarize, they are used to change the direction of the related function this, but call and apply call the related function directly; Bind does not execute the related function, but returns a new function with a new this pointer that can be called manually.

const fn = function () {
    console.log(this, arguments);
}

const target = {};
fn.call(target, 'arg1','arg2');

const target = {};
fn.apply(target, ['arg1', 'arg2']);

const target = {};
fn.bind(target, 'arg1', 'arg2');
Copy the code

The above three pieces of code are equivalent.

Let’s take a look at the following code:

const foo = { name: 'fs', fn: function(){ console.log(this.name); }}; Const bar = {name: 'jun'}; console.log(foo.fn.call(bar)); // '1000 jun'Copy the code

4. Constructor and this

function Fn(){
    this.bar = 'qianjun';
};
const foo = new Fn();
console.log(foo.bar); // 'qianjun'
Copy the code

What does the new operator do?

  • Create a new object.
  • Point the constructor’s this to the new object.
  • Add attributes, methods, and so on to this object.
  • The new object is eventually returned.

Note that if a constructor displays a return, there are two cases:

The constructor display returns a value that is an object, so this refers to the object.

function Fn(){ this.user = 'qianjun'; const o = {}; return o; } const foo = new Fn(); console.log(foo.user); // undefined because foo is {}Copy the code

2. If the return is not an object (returning a primitive type), this still points to the instance.

function Fn(){
    this.user = 'qianjun';
    return 1;
};
const foo = new Fn();
console.log(foo.user); // qianjun
Copy the code

5. This in the arrow function

In arrow functions, the reference to this is determined by the outer (function or global) scope.

const foo = {
    fn: function(){
        setTimeout(function(){
            console.log(this);
        })
    }
}
console.log(foo.fn()); // window
Copy the code

If you need this function to point to foo, you can use the arrow function

const foo = { fn: function(){ setTimeout(() => { console.log(this); }) } } console.log(foo.fn()); / / {fn: ƒ}Copy the code

6. This priority

Explicit binding: The case where call, apply, bind, new bind this is called a display binding.

Implicit binding: The this reference determined by the call relationship is called implicit binding.

Call and apply bindings generally have higher priority.

The new binding has a higher priority than bind.

The binding of the arrow function cannot be modified.