简体   繁体   中英

Understanding “this” within anonymous function in JavaScript

In this post , lots of answers are there discussing the this keyword in JavaScript. However, I am still confuse this in the anonymous function as following

// MyModule.js
'use strict';
(function(handler) {
    // export methods
    handler.B = B;
    handler.A = A;

    function A() {
        console.log(this);
        console.log('function A is invoked...');
    }

    function B() {
        console.log(this);
        console.log('function B is invoked...');
        try {
            A();
            this.A();
        } catch (err) {
            console.log('Exception is ' + err);
        }
    }
})(module.exports);

// test.js
var myModule = require('MyModule.js');
myModule.B();

Output: (Running under Node.js)

{ B: [Function: B], A: [Function: A] }
function B is invoked...

undefined
function A is invoked...

{ B: [Function: B], A: [Function: A] }
function A is invoked...

The output indicates the function A are in two different scopes. Am I right? Why there are two scopes for function A ?

As we know, the this is related to the scope. And the this in the anonymous function of MyModule is undefined . According to the output, one of the scope of function A is undefined , the other is { B: [Function: B], A: [Function: A] } . What the difference between them?

this and scope have almost nothing to do with each other. In JavaScript, this is usually set by how a function is called , not where it's defined. (There are two exceptions to that rule, I'll mention them below.)

So when you're calling A , you're setting what this will be during the call (largely implicitly). When you do this:

A();

...you're calling A without doing anything explicit to set what this should be; as a result, you're implicitly calling it with this set to undefined , because your code is in strict mode. (If it were in loose mode, you'd be calling it with this set to a reference to the global object.) It's also worth noting that you're resolving the identifier A via the context created by the call to your anonymous function, which contains A and B as (effectively) variables.

But here:

this.A();

...you're calling A as part of an expression getting the function reference from an object property ( A ; note that this is a different meaning for A , but that both the property and the context variable refer to the same function). The act of doing that calls A with this set to a reference to the object you got the property from.

That's why you see two different values for this in A .

The exceptions to the " this is set by how you call it" rule are:

  1. ES6's "arrow" functions, which inherit this from the context (not scope) where they're created.

  2. ES5's "bound" functions (the result of calling .bind on a function reference), which have this baked into them by the .bind call and so always see the same value for this .

Usually, this , in a function, is bound to the object on which you called that function.

In your example:

  • You call myModule.B() , this equals to myModule , as you can see from the output: { B: [Function: B], A: [Function: A] }
  • Then, inside the try block you call A() without an object, here this is undefined because you're running in strict mode , otherwise it would point to the global object , which is window in a browser or global in node
  • Finally, the last call is this.A() , here you're basically passing your current this ( myModule ) to the function, so it will be myModule .

The whole this binding is affected only by the way you call a function.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM