This in JavaScript!

Source: Internet
Author: User
Tags sessionstorage

Tip

In JS, this context is always unpredictable, many times the bug is always confused, in fact, as long as the difference between the different circumstances of how to execute on OK.

Global execution

First, let's look at what it is in the global context:

First. 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;

Second. 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).

Perform a purely function call in a function

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:functionconsole.log ( this);  },  foo2: function (console.log (this);    var _this = this;    settimeout (< Span class= "Hljs-keyword" >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;

Another pit of SetTimeout.

As I said before, if you execute the callback function directly without the binding scope, then it is pointing to the Global Object (window), and in strict mode it points to undefined, but the callback function in SetTimeout behaves differently in strict mode:

‘use strict‘;function foo() {  console.log(this);}setTimeout(foo, 1);// window

Supposedly we added strict mode, Foo call also did not specify this, should be out undefined, but here still appear global object, is strict mode invalid?

No, even in strict mode, when the SetTimeout method calls an incoming function, if the function has no specified this, then it does an implicit operation-automatically injecting the global context, equivalent to calling foo.apply (window) rather than foo ();

Of course, if we have specified this when passing in the function, then we will not be injected into the global object, for example: SetTimeout (Foo.bind (obj), 1);

Http://stackoverflow.com/questions/21957030/why-is-window-still-defined-in-this-strict-mode-code

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 (() = {     < Span class= "hljs-built_in" >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// Windowvar 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.

Just remember the arrow function Dafa good, unchanging this.

This in JavaScript!

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.