As for the orientation of this in JS, we should first understand a few concepts:

  • Global variables are mounted under the Window object by default
  • Normally this refers to its caller
  • In es6’s header function, this refers to the creator, not the caller
  • Call, apply, and bind can change the direction of this

When a function is called

Nonstrict mode

const fn1 = function () {
    console.log(this);
    const fn2 = function() {
        console.log(this);
    }
    fn2();//window
}
fn1();//window
Copy the code

In strict mode

'use strict'
const fn1 = function () {
    console.log(this);
    const fn2 = function() {
        console.log(this);
    }
    fn2();//undefined
}
fn1();//undefined
Copy the code

This refers to its caller, so it outputs the window object. However, in strict mode, this is not allowed to refer to the global variable window. So the output is undefined(fn2 refers to the global window by default when the function is called directly. In fact, this is a flaw in JavaScript design. The correct design method is to bind this of the inner function to the object corresponding to the outer function. The programmer comes up with a way to substitute a variable, which is usually called that.)

As object method

const obj = {
    name:'roy'.age:18.infoFun:function(){
        console.log('My name is :'+this.name+', age:+this.age);
        const fn = function(){
            console.log('My name is :'+this.name+', age:+this.age);
        }
        fn();// My name is :undefined, age :undefined
    }
}
obj.infoFun();// My name is Roy. My age is 18
Copy the code

According to the second rule, this refers to its caller, and the caller of infoFun() is obj, so inside infoFun() this refers to its parent object, obj, while the fn output is undefined because of the defect we mentioned earlier. In this case, We usually choose to cache this in the infoFun() method.

const obj = {
    name:'roy'.age:18.infoFun:function(){
        console.log('My name is :'+this.name+', age:+this.age);
        const that = this;
        const fn = function(){
            console.log('My name is :'+that.name+', age:+that.age);
        }
        fn();// My name is Roy. My age is 18
    }
}
obj.infoFun();// My name is Roy. My age is 18
Copy the code

And then f sub n points perfectly.

const obj = {
    name:'roy'.age:18.infoFun:function(){
        console.log('My name is :'+this.name+', age:+this.age); }}const other = obj.infoFun;
other();// My name is :undefined, age :undefined
const data = {
    name:'Tom'.age:20
}
data.infoFun = obj.infoFun;
data.infoFun();// My name is Tom. My age is 20
Copy the code

In this code, we assign infoFun() to the global variable other, call other(), and other is mounted under the global function Window object. The window object has no name and age properties, so the output is undefined. The second piece of code declares the data object, which contains the name and age attributes. In the second rule, normally this refers to its caller. You can see that data is the caller of infoFun(), so it prints the name and age of data.

Triggered as an event in HTML

<body>
  <div id="btn">Click on the I</div>
</body>
<script>
    const btn=document.getElementById('btn');
    btn.addEventListener('click'.function () {
      console.log(this); 
       
})
</script> Copy the code

In this case, the second rule is actually followed. In general, this refers to its caller, this refers to the source of the event, the event.

New keyword (constructor)

const fn=function(name){
    this.name=name;
}
const obj=new fn('roy');  
console.log(obj.name); //roy
Copy the code

The new keyword constructs an object instance, which is assigned to obj, so name becomes the property of the obj object.

Es6 (Shearing function)

const fn1=() = >{
   console.log(this); 
};
fn1(); //Window
const data={
    name:'roy'.infoFun:function(){
      console.log(this); //Object {name: "roy", infoFun: function}
      const fn2=() = >{
        console.log(this); //Object {name: "roy", infoFun: function}
      }
 
      fn2();
    }
  }
  data.infoFun();
Copy the code

According to the third rule: in the es6 header function, this refers to the creator, not the caller. Fn1 is created under the global function, so this points to the global window, while fn2 is created under the object data, so this points to the data object, so inside the fn2 function this points to the data object.

Change the direction of this

Call, apply, and bind can be manipulated to refer to this.

const fn=function(){
   console.log(this);
 }; 
 fn(); //window
 fn.apply({name:"roy"}); //Object {name: "roy"}
Copy the code