Learn how to use this in JavaScript and how to use javascript.

Source: Internet
Author: User
Tags sessionstorage

Learn how to use this in JavaScript and how to use javascript.

Tip

First of all, I know this article is boring. It is nothing more than this in js, and thousands of articles have already written this Part;
However, I still want to write an article about this in js, which is a summary. (You can refer to my other articles)
In js, the context of this is always unpredictable. In many cases, bugs are always confused. In fact, it is okay to know how to execute it in different situations.

Global execution
First, let's look at what this is in the global environment:
First. Browser:

console.log(this);// Window {speechSynthesis: SpeechSynthesis, caches: CacheStorage, localStorage: Storage, sessionStorage: Storage, webkitStorageInfo: DeprecatedStorageInfo…} 

The window object is printed;

Second. node:

 console.log(this);// global 

The global object is printed;

Summary:In the global scope, this executes the current global object (Window in the browser and global in the node ).

Function execution
Pure function call
This is the most common function usage method:

 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 is a global call. At this time, its this points to a global object;

Strict mode 'use strict ';

If you execute pure function calls in strict mode, this will not point to the global, but undefined. this approach aims to eliminate some nonrigorous behaviors in js:

 'use strict';function test() { console.log(this);};test();// undefined 

Of course, it would be better to put it in an immediate execution function to avoid global contamination:

 (function (){ "use strict"; console.log(this);})();// undefined 

Method call 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' 

At this time, this 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' 

It also remains unchanged, because everything in js is an object, and a function is also an object. For test, it is just a function name, a function reference, and it points to this function. When foo = test, foo also points to this function.

If you assign an object method to a variable and then call the variable directly:

 var obj = { name: 'qiutc', foo: function() {  console.log(this); }}var test = obj.foo;test();// Window 

We can see that at this time this executes the global, when we put test = obj. foo and test direct point to a function reference. At this time, it is actually irrelevant to the object obj. Therefore, it is called directly as a normal function. Therefore, this points to a global object.

Pitfalls 

We often encounter some pitfalls in the callback function:

 var obj = { name: 'qiutc', foo: function() {  console.log(this); }, foo2: function() {  console.log(this);  setTimeout(this.foo, 1000); }}obj.foo2(); 

After executing this code, we will find that this printed twice is different:

For the first time, this is printed directly in foo2. Here we point to the object obj, which is beyond doubt;

However, this. foo executed in setTimeout points to a global object. Isn't it used as a function? This is often confusing for beginners;

In fact, setTimeout is just a function, and the function may need parameters. foo is passed to the setTimeout function as a parameter, just as it requires a fun parameter. When passing in the parameter, it actually performs such an operation fun = this. foo, No. Here we direct fun to this. foo reference; when executed, it actually executes fun (), so it has nothing to do with obj. It is directly called as a common function, so this points to the global object.

This problem is common in many asynchronous callback functions;

Solution
To solve this problem, we can use the closure feature to handle it:

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(); 

We can see that using this directly is still a Window; because this in foo2 points to obj, we can store it with a variable _ this, and then use _ this in the callback function, you can point to the current object;

Another pitfall of setTimeout 

Previously, if the callback function is directly executed without binding a scope, this indicates a Global Object (window). In strict mode, this indicates undefined, however, the callback functions in setTimeout are different in strict mode:

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

It is reasonable to say that we have added the strict mode, and foo calls do not specify this. It should be undefined, but there are still global objects. Is the strict mode invalid?

No. Even in strict mode, when the setTimeout method calls the input function, if this is not specified by this function, then it will perform an implicit operation -- automatically inject the global context, equivalent to calling foo. apply (window) instead of foo ();

Of course, if we have already specified this when passing in the function, it will not be injected into global objects, such as setTimeout (foo. bind (obj), 1 );;

Used as a constructor

In js, to implement classes, 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 this points to the object instantiated when the constructor is called;

Of course, constructor is actually a function. If we treat it as a normal function, this still executes the Global:

 function Person(name) { this.name = name; console.log(this);}var p = Person('qiutc');// Window 

The difference is how to call a function (new ).

Arrow Function 

In the new ES6 specification, the arrow function is added, which is the most different from the normal function, that is, the point of this. Do you still remember to use the closure to solve the point of this, if the arrow function is used, the solution is more perfect:

 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 setTimeout execution function, this should be printed in the Window, but here this points to obj, because the reason is that the function (parameter) passed to setTimeout) is an arrow function:

This object in the function body is the object in the definition, rather than the object in use.

Based on the example, we can understand this sentence:
In obj. when foo2 () is executed, the current this points to obj; When setTimeout is executed, we first define an anonymous arrow function, where the key points are located, the object of this execution definition in the arrow function is to point to this in the scope when this function is defined, that is, obj. this in foo2, that is, obj; so when executing the arrow function, its this-> obj. this-> obj; In foo2;

In simple terms, this in the arrow function is only related to the scope of this when it is defined, and has nothing to do with where and how to call it. At the same time, its this point cannot be changed.

Call, apply, bind 

In js, functions are also objects, and there are also some methods. Here we introduce three methods, they can change the point of this in the function:
Call fun. call (thisArg [, arg1 [, arg2 [,...])

It will immediately execute the function. The first parameter is to specify the context of this in the execution function, and the following parameter is the parameter that needs to be passed in to the execution function;
Apply fun. apply (thisArg [, [arg1, arg2,...])

It will immediately execute the function. The first parameter is to specify the context of this in the execution function, and the second parameter is an array, which is the parameter passed to the execution function (the difference from the call );
Bind var foo = fun. bind (thisArg [, arg1 [, arg2 [,...]);

Instead of executing the function, it returns a new function. The context of this is specified for this function. The following parameters are the parameters that need to be passed in for executing the function;

In fact, these three functions are similar. The general purpose is to specify the context (this) of a function. Let's take the call function as an example;

Specify this for a Common Function

 var obj = { name: 'qiutc'};function foo() { console.log(this);}foo.call(obj);// Object {name: "qiutc"} 

As you can see, when foo. call (obj) is executed, this in the function points to the object obj and is successful;

Specify

 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 points to obj2 when executing the function;

Specify this for the constructor

 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(…) 

An error is reported because we have gone to the new Person. call function instead of the Person function. The function here is not a constructor;

Try changing to bind:

 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 the object instantiated by Person, but it has nothing to do with obj, and obj has not changed. this indicates that the context specified by this for Person does not take effect;

Therefore, we can conclude that using bind to specify this for a constructor does not take effect for the new constructor;

Of course, bind can not only specify this, but also input 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"} 

It can be seen that although specifying this does not work, the input parameter still works;

Specify this for the arrow Function 

Let's define a global arrow function, so this in this arrow function will inevitably point to the global object. What if we use the call method to change this:

 var afoo = (a) => { console.log(a); console.log(this);}afoo(1);// 1// Windowvar obj = { name: 'qiutc'};afoo.call(obj, 2);// 2// Window 

We can see that the call operation pointing to this is not successful, so we can conclude that this in the arrow function has decided when defining it (executing this in its scope ), it has nothing to do with how to call and where to call it, including (call, apply, bind) and other operations. this cannot be changed.

Just remember the arrow function.

The above is all the content of this article. I hope it will be helpful for your learning and support for helping customers.

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.