“This is the 8th day of my participation in the First Challenge 2022. For details: First Challenge 2022”

Introduction to the

In JS, there are four binding rules for this: default binding, implicit binding, display binding and new binding. The order of priority for binding is New binding > Explicit binding > Implicit binding > default binding. Let’s explore them one by one.

I wrote and verified each case in the article myself, so I suggest that you execute the case in your browser when reading the article to make it easier to understand.

The default binding

Default binding, which is used when no other binding rule can be applied, usually using global variables or stand-alone function calls.

  1. In a global context, this always refers to a global object (Window), regardless of whether it is in strict mode.
  2. For the callback function inside the delay function this points to the global object Window, regardless of strict mode.
  3. There are two cases of this inside ordinary functions, strict mode and non-strict mode. In non-strict mode, this points to the global object Window by default. Strictly, this refers to undefined.
  4. Under the arrow function, this always points to the global object (Window), regardless of whether it is in strict mode.
console.log("This in the global context:".this); //window

setTimeout(function () {
  console.log(this); //window
});
setTimeout(() = > {
  console.log(this); //window
});

function f1() {
  console.log("Method under this:".this); //window
}
f1();

function f2() {
  "use strict";
  console.log("Strict mode method under this:".this); // undefined
}
f2();

const f3 = () = > {
  console.log("Arrow function method under this:".this); //window
};

f3();

const f4 = () = > {
  "use strict";
  console.log("This: under arrow function method in strict mode".this); //window
};

f4();
Copy the code

Implicit binding

In implicit binding functions are usually called as methods of objects.

  1. When functions are called as methods in an object, theirthisIs the object on which the function is called.
  2. Multiple layers of nested objects, internal methodsthisPoints to the object closest to the function being called.
const obj1 = {
  name: "randy1".say() {
    return this.name;
  },
  b: {
    name: "randy2".say() {
      return this.name; ,}}};console.log(obj1.name); // randy1
console.log(obj1.b.name); // randy2
Copy the code

According to the binding

Explicit binding is easier to understand. It is used to explicitly modify the object referred to by this by call, apply, or bind.

  1. apply(this, [args]),call(this, args),bind(this, args)()The difference is that the apply argument list is an array and bind needs to be called again.
  2. ifcall,applyorbindThe first parameter value passed in isundefinedornullIn strict modethisIs the value passed innull /undefined. The default binding rules applied in non-strict mode,thisPoint to a global object (global in node and Window in browser).
var name = "global name";
function say(age) {
  console.log(`The ${this.name}This year,${age}! `);
}
const user = { name: "randy" };
const user2 = { name: "randy2" };
say(24); // Global name is now 24!
say.apply(user, [25]); // Randy turns 25 this year!
say.apply(user2, [26]); // Randy2 is 26 now!
say.call(user, 25); // Randy turns 25 this year!
say.call(user2, 26); // Randy2 is 26 now!
say.bind(user, 25) ();// Randy turns 25 this year!
say.bind(user2, 26) ();// Randy2 is 26 now!

say.apply(null[25]); // Global name is 25 this year!
say.apply(undefined[26]); // Global name is 26 now!
Copy the code

The new binding

  1. When a function is used as a constructor (using the new keyword), its this is bound to the new object being constructed.
  2. The default value returned by the constructor is the object referred to by this, or you can manually return other new objects.
  3. If the constructor returns a new non-empty object, this points to the new object; otherwise, it points to the object we created.
function People() {
  this.name = "randy";
}

const p1 = new People();
console.log(p1.name); // randy

function People2() {
  this.name = "randy";
  return { name: "demi" }; // Manual setting returns {name: 'demi'} new object
}

const p2 = new People2();
console.log(p2.name); // demi
Copy the code

extension

This in the event

E.target refers to the element that triggered the event, and e.currenttarget refers to the element that bound the event

<div onclick="click1(event)" id="div1">
  <button>This in the event</button>
</div>
Copy the code
function click1(e) {
  // The element that triggers the event
  console.log(e.target); // 
  // Bind the element of the event
  console.log(e.currentTarget); 
      
console.log(this); // window } const div1 = document.getElementById("div1"); div1.addEventListener("click".function (e) { // The element that triggers the event console.log(e.target); // // Bind the element of the event console.log(e.currentTarget);
// Bind the element of the event console.log(this);
console.log(this === e.currentTarget); // true }); Copy the code

This in the arrow function

  1. Arrow functionthisIs bound when a function is defined, not during execution. In simple terms, when a function is defined,thisIt inherits the object that defines the function.
  2. In the arrow functionthisOnly the first one that wraps the arrow functionCommon functionthethisOtherwise, the default binding rules are applied.
  3. Arrow function cannot passapply call bindchangethis.
  4. The arrow function cannot be usedarguments. Have to useresetparameter
  5. Arrow functions cannot be used for constructors.
  6. UnusableyieldCommand, so the arrow function cannot be usedGeneratorFunction.

I will focus on the following examples of the down arrow function binding problem, other features will not be detailed examples, friends can test their own.

const obj = {
  hi: function () {
    console.log(this);
    return () = > {
      console.log(this);
    };
  },
  sayHi: function () {
    return function () {
      console.log(this);
      return () = > {
        console.log(this);
      };
    };
  },
  say: () = > {
    console.log(this); }};let hi = obj.hi(); // Outputs the obj object
hi(); // Outputs the obj object
let sayHi = obj.sayHi();
let fun1 = sayHi(); / / output window
fun1(); / / output window
obj.say(); / / output window
Copy the code

So let’s analyze it.

  1. obj.hi()To apply the implicit binding rule, this is an obj object, so print obj.
  2. hi()The arrow function prints this, applying the property we described above, and this in the arrow function depends only on the first one that wraps the arrow functionCommon functionThis, so the obj object is also output.
  3. obj.sayHi()Returns a normal function.
  4. sayHi()Call the normal function you just returned, apply the default binding rules, and return the Window object.
  5. fun1()The arrow function prints this, applying the property we described above, and this in the arrow function depends only on the first one that wraps the arrow functionCommon functionThis, so the window object is also output.
  6. obj.say()The arrow function prints this, applying the property we described above, and this in the arrow function depends only on the first one that wraps the arrow functionCommon functionIf this is not wrapped in a normal function, the default binding rules apply so the window object is output.

How to judge this accurately

Having said all that, how on earth can we determine if this refers to the problem?

  1. Whether the function is called in new (new binding), and if so, this is bound to the newly created object.
  2. Whether the function is called by call,apply, or by using bind, if so, this binds to the specified object.
  3. Whether the function is called in a context object (implicitly bound), and if so, this binds to that context object.
  4. If none of the above, use the default binding. If in strict mode, it is bound to undefined, otherwise to a global object.
  5. If null or undefined is passed to call, apply, or bind as a binding object for this, these values will be ignored during the call and the default binding rules will apply.
  6. If it is an arrow function, the arrow function’s this depends only on the this of the first normal function that wraps the arrow function. The default binding rules actually apply if they are not wrapped by normal functions.

series

It’s 2022 and you haven’t figured out the JS data type

It’s 2022 and you haven’t figured out JS archetypes and inheritance

It’s 2022 and you haven’t figured out the JS assignment copy, shallow copy, and deep copy

It’s 2022 and you haven’t figured out how to traverse an array of objects

Afterword.

This article is the author’s personal study notes, if there are fallacies, please inform, thank you! If this article has helped you, please click the “like” button