Stop worrying about this: the This mechanism in JS

Source: Internet
Author: User

This article turns from http://web.jobbole.com/82262/

Preface: There are a lot of confusing places in JavaScript, or mechanisms. But these are the things that make JavaScript look so good and different. For example, functions are objects, closures, prototype chain inheritance, and so on, which includes a rather confusing this mechanism. Whether it is a novice or veteran, do not carefully dig a bit and really do not understand this fell on the ground to pinch. Today, we'll take a look at this, and don't worry about this.

1. What is this?

In short, this is one of the many keywords defined in the JavaScript language, which is special in that it is automatically defined in every function domain, but this falls on the ground and leads to a lot of people who don't mind. Here we leave a little suspense, hope to read this article, you can answer this is the guide a very much.

2. What is the use of this?

The audience should ask again, since this is so difficult to understand, then for a very much to use it? Let's look at an example:

1234567891011121314151617 function identify() {    return this.name.toUpperCase();}function sayHello() {    var greeting = "Hello, I‘m " + identify.call( this );    console.log( greeting );}var person1= {    name: "Kyle"};var person2= {    name: "Reader"};identify.call( person1); // KYLEidentify.call( person2); // READERsayHello.call( person1); // Hello, I‘m KYLEsayHello.call( person2); // Hello, I‘m READER
This code is simple, we have defined two functions, identify and SayHello, respectively. And they are implemented in different object environments to achieve the effect of multiplexing, instead of having to write corresponding functions for different object environments in order to perform in different object environments. In short, this gives the function a reuse. There Sir asked again, I do not use this as can be achieved, such as: function identify(context) {      return context.name.toUpperCase(); } function sayHello(context) {      var greeting = "Hello, I‘m " + identify( context);      console.log( greeting ); } var person1= {      name: "Kyle" }; var person2= {      name: "Reader" }; identify( person1); // KYLE identify( person2); // READER sayHello( person1); // Hello, I‘m KYLE sayHello( person2); // Hello, I‘m READER

In a closer look, the solution given by the Sir has indeed achieved similar results. Praise One! What I want to say is that as the code grows, the nesting of functions, the invocation of all levels, and so on are becoming more and more complex, so it becomes increasingly unwise to pass in a reference to an object, which makes your code very messy, even if you can't understand it yourself. The This mechanism provides a more elegant and flexible solution, passing an implicit object reference to make the code more concise and reusable. Well, knowing the usefulness of this, then look at our misunderstanding of it.

3. Misunderstanding about this

Many children's shoes are believed to have learned other languages, and in many programming languages there is a mechanism for this, and inertial thinking brings the understanding of other languages to JavaScript. At the same time, the understanding of this word causes us to have a variety of misunderstandings about it. So, before we start, let's clarify the misunderstanding.

3.1 Misunderstanding one: This refers to the function itself

As we all know, referencing functions in a function can achieve recursion and the effect of assigning values to function properties. This is useful in a number of scenarios. So, many people mistakenly think this is the guiding function itself. For example:

function fn(num) {      console.log( "fn: " + num );      // count用于记录fn的被调用次数      this .count++; } fn.count = 0; var i; for (i=0; i<10; i++) {      if (i > 5) {          fn( i );      } } // fn: 6 // fn: 7 // fn: 8 // fn: 9 console.log( fn.count ); // 0 -- 耶?咋不是4捏?

Above we want to record the number of times FN was called, but the apparent FN was called four times but count is still 0. What's the pinch? Here is a simple explanation, the 4th line of FN in the self-increment implicitly creates a global variable count, because the initial value is undefined, so each time the increment is still not a number, you in the Global Environment Print count (window.count) output should be Nan. The 6th line defines the function familiarity variable count remains unchanged, or 0. If the results of this implementation is not clear, welcome to see my previous days of the blog post (talk about the scope of JS and closure closure scope and closure), here you just need to know, this refers to the function of this understanding is wrong on the line.

This side will be asked again, since this is not a reference function, then I want to implement a recursive function, how to reference it? Here's a quick answer to a question, Two methods: The ① function body uses the function name to refer to the function itself ② function body using Arguments.callee to refer to the function (not recommended). So since the second method is not recommended, how can anonymous functions be quoted? Use the first, and give the anonymous function a functional name (recommended).
3.2 Misunderstanding two: This refers to the lexical scope of the function

This misunderstanding may deceive more people. First, clarify that this does not refer to the lexical scope of function. Indeed, the implementation of the lexical domain in the engine of JS is really like an object, owning properties and functions, but this is just an implementation of the JS engine, which is invisible to the code, that is, the lexical scope "object" is not available in the JS code. (For lexical scopes, if you don't understand, you can refer to a previous post, "Talk about the scope scope and closure closure scope and closure in JS"). Take a look at the wrong example:

function fn1() {      var a = 2;      this .fn2(); //以为this引用的是fn1的词法作用域 } function fn2() {      console.log( this .a ); } fn1(); //ReferenceError

The above code obviously does not perform the desired result, so you can see that this does not refer to the lexical scope of the function. Even, to be sure, in this case fn2 can be executed correctly in fn1 (understanding the lexical scope you know why there is no error in the execution).

4. What does this have to do with what?

Okay, so much has not dried up, and some viewers are starting to close the current page and start to leave. Here, we solemnly declare: this and function where the definition is not a half-gross money relationship, where the function is called to determine what this exactly refers to. That is, this is not the same as the definition of the function, and the function of the implementation of a large relationship. So, remember, "where the function is called determines what this is referring to".

5. The four rules of this mechanism

This is exactly where the object environment is bound or referenced by the function being called. The invocation of a function has a different way of calling, in a different way, to determine which object this reference is determined by four rules. Let's take a look.

5.1 Default binding global variables

This rule is the most common and is the default. When a function is defined and called separately, the rule applied is to bind the global variable. As follows:

function fn() {      console.log( this .a ); } var a = 2; fn(); // 2 -- fn单独调用,this引用window

5.2 Implicit binding

Implicit invocation means that a function call has a context object, as if the function belonged to that object. For example:

12345678 functionfn() {    console.log( this.a );}varobj = {    a: 2,    fn: fn};obj.fn(); // 2 -- this引用obj。

One point to note is that the last object to invoke the function is the context object that is passed to the function (which is a bit of a rip). Such as:

123456789101112 function fn() {    console.log( this.a );}var obj2 = {    a: 42,    fn: fn};var obj1 = {    a: 2,    obj2: obj2};obj1.obj2.fn(); // 42 -- this引用的是obj2.

It is also important to note that the case of the loss of implicit binding is as follows:

12345678910 function fn() {    console.log( this.a );}var obj = {    a: 2,    fn: fn};var bar = obj.fn; // 函数引用传递var a = "全局"; // 定义全局变量bar(); // "全局"

As above, line 8th has implicit binding, but the effect is obviously to assign FN to bar. When the bar executes, it remains the default binding global variable, so the output is as above.

5.3 Show Bindings

Learn that the bind () \apply () \call () function should know that the first parameter it receives is the context object and assigns it to this. Look at the following example:

1234567 functionfn() {    console.log( this.a );}varobj = {    a: 2};fn.call( obj ); // 2

If we pass the first value to a simple value, then the background is automatically converted to the corresponding encapsulated object. If passed to null, the result is binding the default global variables, such as:

12345678 function fn() {     console.log( this.a ); } var obj = {     a: 2 };var a = 10;fn.call( null); // 10

5.4 New Object Binding

If it is a constructor, then it is called with new, then the newly created object is bound. Such as:

12345 functionfn(a) {    this.a = a;}var bar = newfn( 2 );console.log( bar.a );// 2

Note that the general constructor name is capitalized, and there is no capitalization to remind the reader that the constructor is also a general function.

6. Concluding remarks

Read now, 1 questions you should be able to answer. The four kinds of conditions and rules described above for this binding are certainly more and more complex in the process of writing code, but no matter how complex and chaotic they are, they are just a few of the rules and circumstances of a hybrid application. As long as your ideas and understanding are clear, it is certainly not a problem.

Stop worrying about this: the This mechanism in JS

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.