This is the 25th day of my participation in the November Gwen Challenge. Check out the event details: The last Gwen Challenge 2021

Hello everyone, I am a bowl week, a front end that does not want to be drunk (inrolled). If I am lucky enough to write an article that you like, I am very lucky

Writing in the front

The this keyword is one of the most complex mechanisms in JavaScript. It is a special keyword that is automatically defined in the scope of all functions. But even experienced JavaScript developers have a hard time figuring out what it’s pointing to.

In fact, the mechanics of this in JavaScript aren’t that advanced, but developers tend to complicate the process. This plays a very important role in actual development.

This all have one point in common, it always returns an object. Simply put, this is the object where the attribute or method is “currently” located.

This provides a more elegant way to implicitly “pass” an object reference, so the API can be designed to be cleaner and easier to reuse. As future scenarios become more complex, explicitly passing context objects can make code more complex and confusing than using this.

To understand the binding process for this, first understand that the call location is where the function is called in the code (not where it is declared). In general, finding the call location is finding “where the function was called.” The most important thing is to analyze the call stack (that is, all the functions called to get to the current execution location).

Binding rules

The default binding

When using this in a function, when the function is called independently, we can treat this rule as if no other rules apply and apply the default rule. The sample code looks like this:

var v = 100
function fun() {
  console.log(this.v)
}
fun()
Copy the code

In the browser context, this in this function refers to the window object, so 100 is typed; In Node, the result is undefined because the v in Node does not hang on the global object.

Also, in strict mode, this will point to undefiend.

Implicit binding

Implicit binding rules need to consider whether the location of the call has a context object, or whether it is owned or contained by an object. Of course, this is not very accurate, just to help us understand.

The sample code looks like this:

var v = 200
var obj = {
  v: 100.fun: function () {
    console.log(this.v)
  },
}
obj.fun() / / 100
Copy the code

The most common problem with implicit binding is binding loss, which means that the implicitly bound function loses the binding object, meaning that it applies the default binding to bind this to the global object.

The sample code looks like this:

var obj = {
  v: 100.fun: function () {
    console.log(this.v)
  },
}
var fun = obj.fun
fun() //undefined
Copy the code

We assign fun of the obj object to fun of the global object, introducing it into the global scope so that it applies the default binding.

In addition to the above, binding loss can also occur in callback functions, as shown in the following code:

var person = {
  name: 'Bowl Week'.sayMe: function () {
    console.log(this.name)
  },
}
setTimeout(person.sayMe) // undefined
Copy the code

In fact, the default binding rule applied here is equivalent to assigning person.sayMe to a variable and executing it.

Explicitly bound

An explicit binding is the object to which this is bound when the object is called. Function in JavaScript provides implementations of the apply() and call() methods. The first argument to both methods takes an object, binds it to this, and calls the function to this.

In addition to the apply() and call() methods, Function provides explicit binding for bind(), which executes the applied Function, while bind() simply creates a Function to which the new this points.

Example code is as follows:

var obj = {
  v: 100.fun: function () {
    console.log(this.v)
  },
}
var fun = obj.fun

// Through the call() method
fun.call(obj) / / 100

// Use the apply() method
fun.apply(obj) / / 100

// The only difference is the way in which arguments are accepted

/ / use the bind
newFun = fun.bind(obj)
newFun() / / 100
Copy the code

The new binding

In JavaScript, constructors are simply the function to be called using the new operator. All functions, including built-in object functions, can be called with new, which is called a constructor call.

Calling a function with new automatically does the following:

  1. Create a new empty object in the constructorthisPoint to this empty object
  2. Connect the prototype of an object
  3. The constructor method is executed, and properties and methods are added tothisObject referenced
  4. If the function returns no other object thennewThe function call in the expression automatically returns the new object.

Example code is as follows:

function Fun() {
  this.v = 100
}
var fun = newFun()
console.log(fun.v) / / 100
Copy the code

Exceptions to the binding rule

The ignored this

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.

The sample code looks like this:

var v = 200
var obj = {
  v: 100.fun: function () {
    console.log(this.v)
  },
}
obj.fun.call(null) / / 200
Copy the code

Indirect reference

In real development, it is possible to inadvertently create an “indirect reference” to a function, in which case the default binding rules apply when calling the function. Compact references are most likely to occur when assigning, as shown in the sample code below:

var v = 100

function fun() {
  console.log(this.v)
}
var obj = {
  v: 200.fun: fun,
}
var ob = {
  v: 300}; (ob.fun = obj.fun)()/ / 100
Copy the code

The assignment on the last line is equal to the following self-tuning function

; (function () {
  console.log(this.v)
})()
Copy the code

This causes this to refer to the global object.

Matters needing attention

Avoid multiple layers of this

Multiple levels of function or method nesting can result in different levels of this binding objects, as shown in the following example code

var obj = {
  f1: function () {
    console.log(this) / / points to obj
    var f2 = (function () {
      console.log(this) // point to global
    })()
  },
}
obj.f1()
Copy the code

It’s possible that we don’t know where this ends up, leading to some exceptions.

Avoid this in array methods

In the map and forEach methods of arrays, it is allowed to provide a function as an argument. This should not be used inside the function

The sample code looks like this:

var arr = [1.2.3.4.5]
var v = 100
arr.forEach(function () {
  console.log(this.v)
})
Copy the code

This. v refers to the global object

Avoid this in callback functions

This in callback functions often changes the bound object, and the best solution is to avoid this.

The sample code looks like this:

var v = 100

var obj = {
  v: 200.f: function () {
    console.log(this.v)
  },
}

function fn(f) {
  f()
}
fn(obj.f) / / 100
Copy the code

In the code above, the this in the fn() method actually refers to the global object.

Write in the last

This article introduced the concept of this, a reference to this in various locations, and some considerations for using the this keyword.

This is the 55th article in the Start from scratch series, Errors and Anomalies. If you like this column, please give me or the column a look

This series of articles in the nuggets first, preparation is not easy to reprint please obtain permission

Phase to recommend

  • Summary of 42 front-end layout schemes – Juejin (juejin. Cn)
  • JS advanced must be 5 high order functions – nuggets (juejin. Cn)
  • 6 types of inheritance before ES6 – Digging gold (juejin.cn)
  • – Juejin (juejin. Cn)