2

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?

3
  • not two different scopes, two different context, not the same this. Commented Jul 27, 2015 at 11:21
  • On a sitenote, "use strict" should be inside your anonymous function. Commented Jul 27, 2015 at 11:27
  • @koningdavid: It's fine where it is as well, if you don't need to use this at global scope to get at the global object, which the code above doesn't. Commented Jul 27, 2015 at 11:28

2 Answers 2

4

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.

Sign up to request clarification or add additional context in comments.

Comments

0

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.