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
characteristic | data type | describe | Default value |
---|---|---|---|
[[Value]] | Any Javascript type | Contains the data value of this property. | undefined |
[[Writable]] | Boolean | If the Value is false, the [[Value]] attribute of the property cannot be changed. | false |
[[Enumerable]] | Boolean | If the value is true, the property can be used for...in Loop to enumerate. | false |
[[Configurable]] | Boolean | If 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
- This problem can be solved by assigning this value to closed variables.
- 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