Why write this article? I have been asked this question during interviews with Alibaba and other companies before. So I want to share it with you. If you can clearly understand the differences between these seven situations, yes... why write this article?
I have been asked this question during interviews with Alibaba and other companies before. So I want to share it with you. If you can clearly understand the differences between these seven situations, it can be clearly explained to the interviewer. It is undoubtedly a big plus. After understanding this article, the interviewer will not be afraid of asking you how to do this.
When talking about this in Javascript, It is a headache. It is not like Java. this in C ++ points to the object that calls this.
The value of this in a function is determined when the function is actually called and executed, but cannot be determined when the function is defined.
Because the value of this is part of the execution context environment, a new execution Context Environment is generated every time a function is called. When you use this in the Code, the value of this is obtained directly from the context of the execution, rather than from the scope chain.
The value of this can be roughly divided into the following seven situations:
Scenario 1: Global & call of common functions
In the global environment, this always points to the window.
console.log(this === window); //true
When a common function is called (note that it is not a constructor and no new is added before), this also points to window.
var x = 10;function foo(){ console.log(this); //Window console.log(this.x); //10}foo();Case 2: Constructor
The so-called constructor is an Object generated by a new Function. Generally, the first letter of the constructor is capitalized, such as Object, Function, and Array.
function Foo(){ this.x = 10; console.log(this); //Foo {x:10}}var foo = new Foo();console.log(foo.x); //10
In the above Code, if a function is used as a constructor, this indicates the object to be new.
However, if the Foo function is called directly, instead of the new Foo () function, it becomes case 1. At this time, Foo () becomes a normal function.
function Foo(){ this.x = 10; console.log(this); //Window}var foo = Foo();console.log(foo.x); //undefinedCase 3: Object Methods
If a function acts as an object's method, this in the method points to this object.
var obj = { x: 10, foo: function () { console.log(this); //Object console.log(this.x); //10 }};obj.foo();
Note: If you define a function in an object method, the situation is different.
var obj = { x: 10, foo: function () { function f(){ console.log(this); //Window console.log(this.x); //undefined } f(); }}obj.foo();
It can be understood that although function f is defined inside obj. foo, it still belongs to a common function, and this still points to window. (This is a pitfall. Remember it)
Here, if you want to call the variable obj. x in the upper-level scope, you can use self to cache the external this variable.
var obj = { x: 10, foo: function () { var self = this; function f(){ console.log(self); //{x: 10} console.log(self.x); //10 } f(); }}obj.foo();
If the foo function is not called as an object method:
var obj = { x: 10, foo: function () { console.log(this); //Window console.log(this.x); //undefined }};var fn = obj.foo;fn();
Obj. foo is assigned to a global variable and is not called as an attribute of obj. In this case, the value of this is window.
Case 4: constructor prototype attributes
function Foo(){ this.x = 10;}Foo.prototype.getX = function () { console.log(this); //Foo {x: 10, getX: function} console.log(this.x); //10}var foo = new Foo();foo.getX();
In the Foo. prototype. getX function, this points to the foo object. In addition, this represents the value of the current object even in the entire prototype chain.
Case 5: call, apply, or bind a function.
var obj = { x: 10}function foo(){ console.log(this); //{x: 10} console.log(this.x); //10}foo.call(obj);foo.apply(obj);foo.bind(obj)();
When a function is called by call, apply, or bind, the value of this is the value of the input object.
Case 6: DOM event this
In an html dom event handler, this always points to the html dom node bound to the handler:
Function Listener () {document. getElementById ('foo'). addEventListener ('click', this. handleClick); // this indicates the object Listener. It is not emphasized that this} Listener. prototype. handleClick = function (event) {console. log (this );//} Var listener = new Listener (); document. getElementById ('foo'). click ();
This is easy to understand. It is equivalent to passing parameters to the function so that the context changes during the handleClick operation, which is equivalent to the following code:
var obj = { x: 10, fn: function() { console.log(this); //Window console.log(this.x); //undefined }};function foo(fn) { fn();} foo(obj.fn);
You can also use bind to switch the context:
function Listener(){ document.getElementById('foo').addEventListener('click',this.handleClick.bind(this)); }Listener.prototype.handleClick = function (event) { console.log(this); //Listener {}}var listener = new Listener();document.getElementById('foo').click();
The first six cases are summarized as follows: this points to the object that calls this method.
Case 7: this in the arrow Function
When the arrow function is used, the situation is different: this in the arrow function is the lexical scope, determined by the context.
var obj = { x: 10, foo: function() { var fn = () => { return () => { return () => { console.log(this); //Object {x: 10} console.log(this.x); //10 } } } fn()()(); }}obj.foo();
Now, the arrow function completely fixes the point of this, which always points to the lexical scope, that is, the outer caller obj.
If the arrow function is used, the previous hack statement is as follows:
var self = this;
It is no longer needed.
var obj = { x: 10, foo: function() { var fn = () => { return () => { return () => { console.log(this); // Object {x: 10} console.log(this.x); //10 } } } fn.bind({x: 14})()()(); fn.call({x: 14})()(); }}obj.foo();
Because this has been bound to the arrow function according to the lexical scope, this cannot be bound when the arrow function is called using call () or apply, that is, the first parameter is ignored.
Note:
function test(){ var this = {}; //Uncaught SyntaxError: Unexpected token this}
When a language is running, it requires an environment called the host environment.
For JavaScript, a web browser is the most common hosting environment. A browser provides an environment for JavaScript running. In this environment, some interfaces need to be provided so that the JavaScript engine can be connected to the hosting environment.
The JavaScript engine is the place where JavaScript code is actually executed. Common engines include V8 (currently the fastest JavaScript Engine, Google production) and JavaScript core.
Each browser or server (nodejs) has its own JS engine. In the browser, the global object is window, while in nodejs, The global object is global.
The above describes the details of this in Javascript. For more information, see other related articles in the first PHP community!