From: Address: http://www.cnblogs.com/dongcanliang/p/7054176.html Invasion and deletion
preface
This pointing problem is that the knowledge points must be understood at the front end of the pit. Now we have ushered in the ES6 era. Because of the emergence of arrow function, I feel it is necessary to sort out this problem. Therefore, this article
Under the non arrow function, this points to the object that calls the function where it is located, and it points to who is close to whom (this is applicable to conventional objects, prototype chains, getters & setters, etc.); Constructor, this is bound to the created new object; DOM event, this refers to the element that triggers the event; There are two kinds of inline events, bind binding and call & apply methods, which are discussed step by step below. Arrow functions are also discussed.
Global environment
In the global environment, this always points to the global object (window), regardless of strict mode;
console.log(this.document === document); // true // In the browser, the global object is window object: console.log(this === window); // true this.a = 37; console.log(window.a); // 37
Function context call
Function direct call
this in ordinary functions can be divided into two cases, strict mode and non strict mode.
In non strict mode, this points to the global object window by default
function f1(){ return this; } f1() === window; // true
In strict mode, this is undefined
function f2(){ "use strict"; // Here is the strict mode return this; } f2() === undefined; // true
this in object
this of the methods inside the object points to the object that calls these methods,
- The definition position of a function does not affect its this point, which is only related to the object calling the function.
- For multi-layer nested objects, this of the internal method points to the object closest to the called function (window is also an object, and this of the internal object calling method points to the internal object, not window).
//1 var o = { prop: 37, f: function() { return this.prop; } }; console.log(o.f()); //37 var a = o.f; console.log(a()): //undefined var o = {prop: 37}; function independent() { return this.prop; } o.f = independent; console.log(o.f()); // logs 37 //2 o.b = { g: independent, prop: 42 }; console.log(o.b.g()); // logs 42
this in prototype chain
this of the method in the prototype chain still points to the object calling it, which is consistent with the above discussion; For example,
var o = { f : function(){ return this.a + this.b; } }; var p = Object.create(o); p.a = 1; p.b = 4; console.log(p.f()); // 5
It can be seen that there is no attribute f in P. when p.f() is executed, the prototype chain of P will be found, and the F function will be found and executed. However, this has nothing to do with this pointing to the object P in the function. Just remember who calls and points to whom.
The above is also applicable when the function is called as a getter & setter.
this in constructor
this in the constructor is bound to the new object being created.
Note: when the default value returned by the constructor is an object referenced by this, you can manually set it to return other objects. If the return value is not an object, return this.
function C(){ this.a = 37; } var o = new C(); console.log(o.a); // logs 37 function C2(){ this.a = 37; return {a:38}; } var b = new C2(); console.log(b.a); // logs 38
The internal this of the above two examples points to the object o. you might as well execute the above code on the console to see the objects o and b. These are the contents of the constructor, which will not be introduced here. (this.a = 37 in C2 function has no effect on the whole process and can be ignored).
call & apply
When a Function is called through the call() and apply() methods inherited from the prototype of the Function object, the internal this value of the Function can be bound to the first object specified by the call() & apply() method. If the first parameter is not an object, JavaScript will try to convert it into an object and point to it.
example:
function add(c, d){ return this.a + this.b + c + d; } var o = {a:1, b:3}; add.call(o, 5, 7); // 1 + 3 + 5 + 7 = 16 add.apply(o, [10, 20]); // 1 + 3 + 10 + 20 = 34 function tt() { console.log(this); } // The returned object is shown in the figure below (Figure 1) tt.call(5); // Number {[[PrimitiveValue]]: 5} tt.call('asd'); // String {0: "a", 1: "s", 2: "d", length: 3, [[PrimitiveValue]]: "asd"}
bind method
The bind method is introduced in ES5. On the prototype chain of Function, Function prototype. bind. After binding through the bind method, the Function will always be bound to its first parameter object, regardless of when it is called.
function f(){ return this.a; } var g = f.bind({a:"azerty"}); console.log(g()); // azerty var o = {a:37, f:f, g:g}; console.log(o.f(), o.g()); // 37, azerty
This in DOM event handler & this in inline event
DOM event handler
- When the function is treated as a listening event handler, its this points to the element that triggers the event (for the addEventListener event)
// When called, turns the associated element blue function bluify(e){ //Print the clicked element on the console console.log(this); //Stop time bubbling e.stopPropagation(); //Block default events for elements e.preventDefault(); this.style.backgroundColor = '#A5D9F3'; } // Gets a list of all elements in the document var elements = document.getElementsByTagName('*'); // Take bluefy as the click listening function of the element. When the element is clicked, it will turn blue for(var i=0 ; i<elements.length ; i++){ elements[i].addEventListener('click', bluify, false); }
The above code is recommended to execute the following in the web page to see the effect.
Inline events
this pointing in inline events can be divided into two cases:
- When the code is called by the inline handler function, its this points to the DOM element where the listener is located
- When the code is executed inside the function, its this point is equivalent to the direct call of the {function, that is, it points to the global object window in the non strict mode and undefined in the strict mode
Code block for page
Displays three buttons in the browser
Click the three buttons above in turn to output the results on the console,
It is recommended to operate it again for better understanding.
setTimeout & setInterval
For the callback function inside the delay function, this point of the function points to the global object window (of course, we can change this point of its internal function through the bind method)
See the code and screenshot below
//Code by default function Person() { this.age = 0; setTimeout(function() { console.log(this); }, 3000); } var p = new Person();//Return the window object after 3 seconds ============================================== //Bind by bind function Person() { this.age = 0; setTimeout((function() { console.log(this); }).bind(this), 3000); } var p = new Person();//After 3 seconds, return the newly generated object Person {...}
this in arrow function
Since the arrow function does not bind this, it will capture the this value of the context in which it is located (i.e. the defined location) as its own this value,
- Therefore, the call() / apply() / bind() method only passes in parameters for the arrow function, and has no effect on its this.
- Considering that this is at the lexical level, the rules related to this in the strict mode will be ignored. (you can ignore the impact of whether it is in strict mode)
Because the arrow function can capture the this value of its context, so
function Person() { this.age = 0; setInterval(() => { // The 'this' variable in the callback points to the expected object this.age++; }, 3000); } var p = new Person();
The above code can get the value we want. As shown in the figure below, this in setTimeout points to the object newly generated by the constructor, while the ordinary function points to the global window object
var adder = { base : 1, add : function(a) { var f = v => v + this.base; return f(a); }, addThruCall: function inFun(a) { var f = v => v + this.base; var b = { base : 2 }; return f.call(b, a); } }; console.log(adder.add(1)); // Output 2 console.log(adder.addThruCall(1)); // It still outputs 2 (instead of 3). Its internal this has not changed due to call(). Its this value is still the this value of the function inFun, pointing to the object adder
Bind() & apply() readers can test by themselves
Sample code for strict mode (can be copied into the console for verification)
var f = () => {'use strict'; return this}; var p = () => { return this}; console.log(1,f() === window); console.log(2,f() === p()); //1 true //2 true
The above arrow functions are all inside the method. In short, they are used in a non method way. What if the arrow function is used as a method?
Above example
var obj = { i: 10, b: () => console.log(this.i, this), c: function() { console.log( this.i, this) } } obj.b(); // undefined window{...} obj.c(); // 10 Object {...}
You can see that the arrow function this as a method points to the global window object, while the ordinary function points to the object that calls it
Comment area @ return_ to_ The conclusion here is wrong. Look at the example
let p = { a: function () { var obj = { i: 10, b: () => {console.log(this.i, this)}, c: function () { console.log(this.i, this) } } obj.b() } } p.a()
Run the above code and see that , this , is , p. the previous conclusion points not to the window, but to the context of the currently defined variable
In short, the arrow function this as a method points to the current context.
The above is the content of personal learning and sorting. The examples in the article refer to MDN. Welcome to exchange and study