this Parsing of JavaScript

To say that JavaScript is the language's most confusing point of knowledge, this keyword is definitely one. Learning this will expand your knowledge and deepen your understanding of the code. Even if you don't intend to use it in your code base, knowing where this is going will help you take over someone else's code and understand its logic.

1. Pointing in ordinary functions

(1) If there is this in a function, but it is not called by the previous level object, then this points to window (non-strict mode)/ undefined (strict mode).

function a(){     
  var user = "Li Ming"     
  console.log(this); // The non-strict mode is window and the strict mode is undefined         
  console.log(this.user); //Unstrict mode undefined, strict mode error 
} 
a(); 

(2) If there is this in a function and the function is called by a higher level, this is the object of the higher level.

var o = {     
  user:"Li Ming",     
  fn:function(){         
    console.log(this.user);  //Li Ming     
  } 
};
o.fn(); 

(3) If there is this in a function, the function contains more than one object, although the function is called by the outermost object, this only points to the object at its superior level.

var o = {     
  a:10,     
  b:{         
    a:12,         
    fn:function(){             
      console.log(this.a); // 12         
    }     
  } 
}; 
o.b.fn(); 

Summary: this always points to the object that last called it, that is, to see who called it when it was executed.
Note: If a function containing this is assigned to a variable and the object is executed separately, then this point to window (non-strict mode)/ undefined (strict mode).

var o = {     
  a:10,     
  b:{         
    a:12,         
    fn:function(){             
      console.log(this); // The non-strict mode is window and the strict mode is undefined                
      console.log(this.a); //Unstrict mode undefined, strict mode error         
    }     
  } 
}; 
var j = o.b.fn; //Assigning fn to variable j did not execute 
j();  //Executed, but it was not called by the previous level

2. Pointing in Constructors

(1) No return in constructor
this points to an instance of the function.
Because: the new keyword creates an empty object and then automatically calls apply() to point this empty object. Creating an instance is equivalent to copying a constructor into the instance object.

function Fn(){     
  this.user = "Li Ming"; 
}; 
var a = new Fn();  // Fn {user:'Li Ming'} 
console.log(a.user); // Li Ming 

(2) return in constructor
If a value of reference type is returned, after creating an instance with new, this points to the returned value. If the return value is not a reference type value, this is still an instance of the function.

/* * Example 1 */ 
function Fn(){       
  this.user = 'Li Ming';       
  return [1,2];  // Or {}, or function(){} 
}; 
var a = new Fn;   
console.log(a);  // [1,2] 
console.log(a.user); // undefined 
/* * Example 2 */ 
function Fn()   {       
  this.user = 'Li Ming';       
  return {user:"lily"};   
}; 
var a = new Fn;  
console.log(a); // {user: "lily"} 
console.log(a.user); //lily 
/* * Example 3 */ 
function Fn()   {       
  this.user = 'Li Ming';       
  return 1; // Or String, or Boolean, or Symbol, or undefined, or null 
};
var a = new Fn;   
console.log(a); // fn {user:'Li Ming'} 
console.log(a.user); // Li Ming 

Extension: When using the new operator, parentheses can be omitted to simplify writing if there are no parameters to pass. However, some tools may consider this to be nonstandard and alert you.
Note, however, that parentheses are different when using the new operator with property calls. (because. takes precedence over new)

function Fn()   {       
  this.user = 'Li Ming';   
}; 
var a = new Fn.user;   // Fn.user is not a constructor 
var b = new Fn().user;  // 'Li Ming' 

3. Pointing in Event Functions

This points to the label that triggered this event.

<button class="btn1">button1</button>

<body>
    <button class="btn1">button1</button>
    <button class="btn2">button2</button>
    <button class="btn3">button3</button>
    <script type="text/javascript">
            
            
        for(var i = 1; i < 4; i++) {
            var btn = document.getElementsByClassName('btn'+i)[0];
            btn.onclick = function () {
                    console.log(this); //Corresponding tags for btn1, btn2, and btn3, respectively
            }
        } 
    </script>
</body>

Be careful:

 <button onclick="handleClick()"></button>
 <script>
    function handleClick(){
        console.log(this);  //Window
    };
</script>

4. Direction in Timer

this points to window.

setInterval( function () {
    console.log(this);  //window
},1000);

setTimeout(function() {
    console.log(this);  //window
}, 1000)


var a = 23;
function Demo() {
      this.a = 12;
      var self = this;
      setInterval(this.show, 1000);
}
Demo.prototype.show = function() {
    alert(this.a);
};
var demo = new Demo();
demo.show();
// 12
// 23.........23

5. Pointing in Arrow Functions

The arrow function does not bind this, its this comes from the upper level of the scope chain.

function foo() {
  setTimeout(() => {
    console.log(id); // {id: 42}
    console.log('id:', this.id);  // id: 42
    //The function in setTimeout uses the arrow function, so it will be consistent with the outer this, which is {id: 42}
    //If you have a normal function in setTimeout, this should point to the global object window when executed, which should output 21.
  }, 100);
}
var id = 21;
foo.call({ id: 42 });

The this point of the arrow function cannot be modified with call/apply/bind; it is fixed.

function foo() {
    //Return Arrow Function
    return(a) => {
        //this inherits from foo()
        console.log(this.a);
    };
}
var obj1 = {
    a:2
};
var obj2 ={
    a:3
};
var bar = foo.call(obj1);
bar.call(obj2); //2, not 3!!!
//The pointing of the arrow function this object is fixed, so the call that follows does not modify the binding.

6. You can use call/apply/bind to modify this pointing (except for arrow functions)

Note: When call/apply/bind is used for arrow functions, only parameters can be passed, not bound to this. (Their first parameter will be ignored)

const obj = {
    a: () => {
        console.log(this)
    }
}
obj.a.call('123')  //The result is still a window object
//The arrow function itself and the level a are in the form of key:value, that is, the object where the arrow function itself is located is obj, and the this of obj is window, so this is actually window here

7. Direction of this in strict and non-strict modes in global scope

In non-strict mode, the default this is window;
Strict mode ("use strict;") The default this is undefined.
Exceptions:
1. When the callback function of the timer is a normal function, this points to window in both strict and non-strict modes.
2. In an arrow function, this is the upper level of the scope of the arrow function. If it is a global scope, this points to window in both strict and non-strict modes (because in ES6, this points to window in global scope, whether it is a strict mode or not).

Keywords: Javascript Front-end

Added by qaokpl on Sat, 25 Dec 2021 08:19:28 +0200