This in JavaScript points to the problem

Source: Internet
Author: User
Tags sessionstorage

Global execution
First, let's look at what it is in the global context:
Browser:
Console.log (this);
Window {speechsynthesis:speechsynthesis, caches:cachestorage, Localstorage:storage, Sessionstorage:storage, Webkitstorageinfo:deprecatedstorageinfo ...}
You can see that the Window object is printed out;
Node
Console.log (this);
Global
You can see that the global object is printed out;

Summary: It executes the current global object in the global scope (the browser side is global in Window,node).

function to execute the

Purely function calls

This is the most common way to use a function:

function Test () {
Console.log (this);
};

Test ();
Window {speechsynthesis:speechsynthesis, caches:cachestorage, Localstorage:storage, Sessionstorage:storage, Webkitstorageinfo:deprecatedstorageinfo ...}
We can see that when a function is called directly, it belongs to the global call, when it points to the global object;

Strict mode ' use strict ';

If a purely function call is performed in strict mode, then this does not point to the global, but undefined, in order to eliminate some of the non-rigorous behavior of JS:

' Use strict ';
function Test () {
Console.log (this);
};

Test ();

Undefined
Of course, it would be better to put it in an immediate execution function, avoiding the overall pollution:

(function () {
"Use strict";
Console.log (this);
})();

Undefined
Method invocation as an object

When a function is called as a method of an object:

var obj = {
Name: ' QIUTC ',
Foo:function () {
Console.log (this.name);
}
}

Obj.foo ();

' QIUTC '
This time, this point points to the current object;

Of course, we can also do this:

function Test () {
Console.log (this.name);
}
var obj = {
Name: ' QIUTC ',
Foo:test
}

Obj.foo ();

' QIUTC '
Same constant, because in JS everything is an object, the function is an object, for test, it is just a function name, a function of reference, it points to this function, when foo = Test,foo also pointed to the function.

If the object's method is assigned to a variable, then the variable is called directly:

var obj = {
Name: ' QIUTC ',
Foo:function () {
Console.log (this);
}
}

var test = Obj.foo;
Test ();

Window
As can be seen, this time this is performed globally, when we put test = Obj.foo, test directly points to a reference to a function, this time, it is actually not related to the object obj, so it is used as a normal function to call directly, so, this point to the global object.

Some pits

We often encounter some pits in the callback function:

var obj = {
Name: ' QIUTC ',
Foo:function () {
Console.log (this);
},
Foo2:function () {
Console.log (this);
SetTimeout (This.foo, 1000);
}
}

Obj.foo2 ();
Executing this code we will find that two times the print out of this is not the same:

For the first time, this is printed directly in Foo2, which points to the Obj object, which we have no doubt;

But This.foo, which executes in setTimeout, points to the global object, isn't it used as a function method? This often makes many beginners puzzled;
In fact, SetTimeout is just a function, the function is necessarily likely to need parameters, we put This.foo as a parameter to setTimeout this function, as it needs a fun parameter, when passed in the parameters, in fact, did a such operation fun = This.foo, see no, here we direct the fun point to the This.foo reference, the execution of the time is actually executed fun () so it has nothing to do with obj, it is called as a normal function directly, so this point to the global object.

This problem is commonly encountered in many asynchronous callback functions;

Solve

To solve this problem, we can use the characteristics of closures to deal with:

var obj = {
Name: ' QIUTC ',
Foo:function () {
Console.log (this);
},
Foo2:function () {
Console.log (this);
var _this = this;
SetTimeout (function () {
Console.log (this); Window

Console.log (_this); Object {name: "QIUTC"}
}, 1000);
}
}

Obj.foo2 ();
Can be seen directly with this is still the Window; because this in foo2 points to obj, we can store it with a variable _this first, then use _this in the callback function to point to the current object;

Use as a constructor

In JS, in order to implement the class, we need to define some constructors, when calling a constructor, we need to add the New keyword:

function person (name) {
THIS.name = name;
Console.log (this);
}

var p = new Person (' QIUTC ');

person {name: "QIUTC"}
We can see that when called as a constructor, this points to the object instantiated by the constructor call;

Of course, the constructor is actually a function, and if we take it as a normal function, this one still performs the global:

function person (name) {
THIS.name = name;
Console.log (this);
}

var p = person (' QIUTC ');

Window
The difference is how the function is called (new).

Arrow functions

In the new specification of ES6, the arrow function is added, which is the most different from the normal function is the point of this, remember in the above (as the object of the method call-some pits-solve) we use closures to solve the problem of this point, if the use of the arrow function can be more perfect solution:

var obj = {
Name: ' QIUTC ',
Foo:function () {
Console.log (this);
},
Foo2:function () {
Console.log (this);
SetTimeout (() = {
Console.log (this); Object {name: "QIUTC"}
}, 1000);
}
}

Obj.foo2 ();
As you can see, in the function that setTimeout executes, it should have been printed in Window, but here this is pointing to obj, because the function (parameter) passed to SetTimeout is an arrow function:

The This object in the body of the function is the object that is defined, not the object that is used.
Let's take a look at this sentence by example:
At the time of Obj.foo2 () execution, the current this point points to obj, and in the execution of SetTimeout, we first define an anonymous arrow function, where the key is the object in which this is defined when the this arrow function is defined, which is the scope of the This, which is the this in Obj.foo2, that is, obj; so when the arrow function is executed, it's this------and obj in Obj.foo2;

Simply put, the this in the arrow function is only relevant to the scope that defines it, not to where and how it is called, while its this point is immutable.

Call, apply, bind

In JS, the function is also an object, there are also some methods, here we introduce three methods, they can change the function of this point:

Pager
Fun.call (thisarg[, arg1[, arg2[, ...])
It executes the function immediately, the first parameter is the context that specifies the this in the execution function, and the following arguments are the parameters that the function needs to pass in;

Apply
Fun.apply (thisarg[, [Arg1, Arg2, ...])
It executes the function immediately, the first parameter is the context that specifies the this in the execution function, the second argument is an array, and is the argument to the execution function (the difference from call);

Bind
var foo = fun.bind (thisarg[, arg1[, arg2[, ...]);
Instead of executing the function, it returns a new function that is assigned the context of this, and the arguments that follow are the parameters that the function needs to pass in;

These three functions are actually quite similar, the general purpose is to specify a function context (this), we take the call function as an example;

Specify this for a normal function

var obj = {
Name: ' QIUTC '
};

function foo () {
Console.log (this);
}

Foo.call (obj);

Object {name: "QIUTC"}
As you can see, in the execution of Foo.call (obj), this object in the function points to obj, which is successful;

Specify a this for the methods in the object

var obj = {
Name: ' QIUTC ',
Foo:function () {
Console.log (this);
}
}

var obj2 = {
Name: ' tcqiu222222 '
};

Obj.foo.call (OBJ2);

Object {name: "tcqiu222222"}
As you can see, this is where the function is executed, which points to the OBJ2, success;

Specify this for the constructor function

function person (name) {
THIS.name = name;
Console.log (this);
}

var obj = {
Name: ' qiutc2222222 '
};

var p = new Person.call (obj, ' qiutc ');

Uncaught TypeError:Person.call is not a constructor (...)
Here's a mistake because we went to new Person.call function, not person, here is not a constructor function;

Change to bind try:

function person (name) {
THIS.name = name;
Console.log (this);
}

var obj = {
Name: ' qiutc2222222 '
};

var Person2 = person.bind (obj);

var p = new Person2 (' QIUTC ');

person {name: "QIUTC"}

Console.log (obj);

Object {name: "qiutc2222222"}
The printed object is instantiated by the person, and obj has no relation, and obj has not changed, stating that we have given the person the this context is not in effect;

Therefore, it can be concluded that by using bind to assign this to a constructor, the this specified by the BIND function does not take effect at the time of the new constructor.

Of course bind can not only specify this, but also pass in parameters, let's try this operation:

function person (name) {
THIS.name = name;
Console.log (this);
}

var obj = {
Name: ' qiutc2222222 '
};

var Person2 = person.bind (obj, ' qiutc111111 ');

var p = new Person2 (' QIUTC ');

person {name: "qiutc111111"}
As you can see, although specifying this does not work, the incoming parameters still work;

Specify this for the arrow function

Let's define a global arrow function, so this one in the arrow function will necessarily point to the global object, and if you change this with the call method:

var Afoo = (a) + = {
Console.log (a);
Console.log (this);
}

Afoo (1);

1
Window

var obj = {
Name: ' QIUTC '
};

Afoo.call (obj, 2);

2
Window
As you can see, the call to this here is not successful, so it can be concluded that the this in the arrow function has been determined at the time it was defined (the this in the scope where it was defined), regardless of how it was called and where it was called, including (calls, apply, bind), etc. The operation cannot change its this.

This in JavaScript points to the problem

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.