JavaScript what is this? From simple to deep, understand thoroughly

Posted by Zack on Sun, 30 Jan 2022 20:37:47 +0100

this keyword is a keyword in JavaScript, and it is also a required test for junior high school students.

The way the function is called determines the value of this (runtime binding). This cannot be assigned during execution, and the value of this may be different every time the function is called
—MDN

We can initially understand that using me, I point to who this is, and this, as a pointer, always points to the caller.

What is this?

this is an object automatically generated inside the function body when the function is running. It can only be used inside the function body

Simple function call:

function test() {
	this.name = "code"
  console.log(this === window)  
	console.log(this.name)
}
test() // code 

If we print this === window in the test function and the result is true, expand the window object to see that there is a name attribute with the value of code

Call as object method:

// demo1
function test() {
  console.log(this === window)
	console.log(this.name)
}
let obj = {name: 'wccode'}
obj.fun = test
obj.fun() // false, wccode

// demo2
let demo1 = {name:'demo1',fun:test}
let demo2 = {name:'demo2',fun:test}
demo1.fun() //demo1
demo2.fun() //demo2

The value of this depends on how the function is called.

Understand this?

The reason why JavaScript language has this design is related to the data structure in memory:

Data type:

Value type (basic type): String, number, Boolean, Null, Undefined, Symbol.
Reference data types: object, array, function.

Data structure:
**
In computer science, objects are objects in memory that can be identifier In Javascript, an object can be regarded as a collection of attributes.
**
Attributes of a data property

characteristicdata typedescribeDefault value
[[Value]]Any Javascript typeContains the data value of this property.undefined
[[Writable]]BooleanIf the Value is false, the [[Value]] attribute of the property cannot be changed.false
[[Enumerable]]BooleanIf the value is true, the property can be used for...in Loop to enumerate.false
[[Configurable]]BooleanIf the Value is false, the property cannot be deleted, and the properties other than [[Value]] and [[Writable]] cannot be changed.false

It is strongly recommended to read: JavaScript data types and data structures | MDN

Assign an object to variable obj:

let obj = { name: "code" }
// The object is a reference type. After the JS engine generates the object in memory, it actually assigns the memory address of the object to the variable obj. That is, the variable obj is an address (Reference)
obj.name
// The JS engine first gets the memory address from obj, then reads the original object from the address and returns its name attribute

Functions also belong to reference type, so functions can be executed in different operating environments. Therefore, a mechanism is needed to obtain the current operating environment (context) inside the function body. This is for this demand. The purpose is to obtain the current operating environment of the function inside the function body. This is also innocent~

Understand this and use scenarios

Global environment

The global environment uses this, which points to the top-level object.

this === window // true

function f() {
  console.log(this === window);
}
f() // true

Constructor

Use this in the constructor, which points to the instance object.

var Obj = function (p) {
  this.p = p;
};
var o = new Obj('Hello World!');
o.p // "Hello World!"

Methods within objects

This rule is too deep for you to grasp

Normal conditions:

var obj ={
  foo: function () {
    console.log(this);
  }
};

obj.foo() // obj obj.foo execution, internal this points to obj

Exception 01:

Referring to Mr. Ruan's article, what Mr. Ruan wrote here is a little difficult to understand

// Situation 1
(obj.foo = obj.foo)() // window
// Situation II
(false || obj.foo)() // window
// Situation III
(1, obj.foo)() // window

The above three situations can be understood as:

let test = obj.foo
test() // window

As mentioned earlier, functions are reference types, and so are functions in objects, obj and obj Foo is two storage addresses. The above situations are equivalent to giving the foo memory address to test and calling test() directly. The running environment is the global environment, so this points to the global environment.
Exception 02:
Object package object. This will not look up like a variable. Remember that this points to the caller.

var a = {
  p: 'Hello',
  b: {
    m: function() {
      console.log(this.p);
    }
  }
};

a.b.m() // undefined

// amount to 

var b = {
  m: function() {
   console.log(this.p);
  }
};

var a = {
  p: 'Hello',
  b: b
};

(a.b).m() // Equivalent to b.m()

reform:

var a = {
  b: {
    m: function() {
      console.log(this.p);
    },
    p: 'Hello'
  }
};

var hello = a.b.m;
hello() // undefined

Why is hello() undefined? Draw the key point. Again, function is a reference type. m is actually an address of the function. Directly using hello = a.b.m is equivalent to assigning the function address to the Hello variable and executing hello(). It is executed in the global environment at this time, so this P is undefined.

Arrow function

The arrow function does not define this binding

Use the previous example for comparison

var obj ={
  foo: ()=> {
    console.log(this);
  }
};

obj.foo() // window 

Switch / bind this

JavaScript provides three methods, call, apply and bind, to switch / fix the direction of this, which will not be introduced here

call & apply

// Object can be passed as the first parameter of bind or apply, and the parameter will be bound to the object.
var obj = {a: 'Custom'};

// Declare a variable and take it as an attribute of the global object window.
var a = 'Global';

function whatsThis() {
  return this.a;  // The value of this depends on how the function is called
}

whatsThis();          // 'Global' because this is not set in this function, it defaults to the Global / window object
whatsThis.call(obj);  // 'Custom' because this in the function is set to obj
whatsThis.apply(obj); // 'Custom' because this in the function is set to obj

bind

ECMAScript 5 introduces Function.prototype.bind() . Calling f.bind(someObject) will create a function with the same function body and scope as F, but in this new function, this will be permanently bound to the first parameter of bind, no matter how the function is called.

function f(){
  return this.a;
}

var g = f.bind({a:"azerty"});
console.log(g()); // azerty

bind should be used with caution
Each time the bind() method runs, a new function is created.
First, there will be performance problems. Second, closures will be generated. If they are applied in event binding, they cannot be cancelled.

Best practices

  1. This problem can be solved by assigning this value to closed variables.
  2. Avoid using global variables and save references to other objects in the local scope

Reference link:

Ruby javascript advanced programming
MDN | this
MDN | JavaScript data types and data structures
Ruan Yifeng's this usage of Javascript
Ruan Yifeng JavaScript tutorial