This refers to the problem, because it involves many knowledge points, it is always not well understood at the beginning of learning. Reading too many documents makes me confused. I read Mr. Bo's documents again and again today and took this opportunity to write down some of my own ideas to consolidate my memory and deepen my understanding.
🍓 Reference: advanced front end Foundation (VII): comprehensive interpretation of this
At the beginning of learning, there was a saying that won my heart: whoever calls it, this points to who.
The "it" here refers to the function, who calls this function, and who is in this function this Just point to who.
This statement is not entirely true. In the process of later development, I gradually realized that this statement is very irresponsible.
When was this determined?
First, the first question, when did this point be determined?
We review the execution context. In the creation phase, the execution context does three things:
- Create variable object
- Establish scope chain
- Make sure this points to
this point is determined in the execution context creation stage. When was the execution context created?
- The execution context can be simply understood as the execution environment of the current code, which will create a scope;
- The execution environment is divided into global environment, function environment and eval (not used in most cases and can be ignored);
- The global execution context is created as soon as the script code starts running;
- The execution context of the function is created when the function is called;
When I know "OK" this point->Execution context creation phase->After the "function called" set, I tried to ask myself, "What happened to the calling function? " Before I answered, I realized that I still needed a deep understanding and memory.
Conclusion: this point is determined during the execution context creation phase
We can also understand it as "this point is determined when the function is called", but we must remember that calling the function will create an execution context, and then determine this point.
Who does this point to?
Because this point is determined when calling a function, the this point of a function can be very flexible. In the following example, the same function points to different objects due to different calling methods.
var a = 10; var obj = { a: 20 } function fn() { console.log(this.a); } fn(); // 10 fn.call(obj); // 20. Use call to change the direction of this
In addition, once this is determined during function execution, it cannot be changed.
var a = 10; var obj = { a: 20 } function fn() { this = obj; // This sentence attempts to modify this, and an error will be reported after running console.log(this.a); } fn();
1, this in global object
this of the global object is a special existence, pointing to itself, that is, to the global environment.
// Bind to global object through this this.a2 = 20; // Bound to a variable object by declaration, but in the global environment, the variable object is itself var a1 = 10; // Only with the assignment operation, the identifier is implicitly bound to the global object a3 = 30; // The output results will all meet the pre-test requirements console.log(a1); console.log(a2); console.log(a3);
2, this in function
- In a function context, this is provided by the caller and is determined by the way the function is called.
- If the caller function is owned by an object, the internal this points to the object when the function is called.
- If the function is called independently, this inside the function points to undefined.
- In non strict mode, when this points to undefined, it is automatically pointed to the global object
To accurately determine this It is very important to find the caller of the function and distinguish whether he is an independent call.
// For accurate judgment, we use strict mode inside the function, because the non strict mode will automatically point to the global function fn() { 'use strict'; console.log(this); } fn(); // fn is the caller and is called independently window.fn(); // fn is the caller and is owned by window
Another difficult example:
var a = 20; var foo = { a: 10, getA: function () { return this.a; } } console.log(foo.getA()); // 10 var test = foo.getA; console.log(test()); // 20
test() is the caller. Although it is the same as the reference of foo.getA(), it is called independently. Therefore, this points to undefined. In the non strict mode, it automatically turns to the global window.
var a = 20; function getA() { return this.a; } var foo = { a: 10, getA: getA } console.log(foo.getA()); // 10 function foo() { console.log(this.a) } function active(fn) { fn(); // Real caller, independent call } var a = 20; var obj = { a: 10, getA: foo } active(obj.getA);
3, Use call and apply to display the specified this
JavaScript internally provides a mechanism that allows us to manually set the direction of this, that is, call and apply.
When you understand call and apply, remember that it should be understood as calling a function and specifying this as the desired object, rather than letting the object call a method that does not belong to it.
function fn(num1, num2) { console.log(this.a + num1 + num2); } var obj = { a: 20 } fn.call(obj, 100, 10); // 130 fn.apply(obj, [20, 10]); // 50
The parameters after call and applay are passed to the function to be executed. Call is passed one by one, and apply is passed in the form of array. This is the only difference between them.
4, this in constructor
function Person(name, age) { // Who does this point to here? this.name = name; this.age = age; } Person.prototype.getName = function() { // Who does this point to here? return this.name; } // Are the above two this the same? Do they point to the prototype object? var p1 = new Person('Nick', 20); console.log(p1.getName()); // "Nick"
When calling the constructor through the new operator, it will go through the following four stages:
- Create a new object;
- Point this of the constructor to the new object (the original constructor is called independently, and the internal this points to undefined);
- Execute the code of the constructor and add properties, methods, etc. to the object;
- Return a new object;
When the new operator calls the constructor, this actually points to the newly created object. Finally, the new object is returned and accepted by the example object. So we can say that this of the constructor points to the new instance object.