2

Assuming I have two files. One file with a class where the method hello just console.logs this:

// Class.js
class Test {
  constructor() {
    this.inside = true;
  }

  hello() {
    console.log('inside hello')
    console.log(this);
  }
}

module.exports = new Test();

and another file which executes the method hello of this class:

// index.js
const Test = require('./Class.js');

Test.hello();
// -> 'inside hello'
// -> { inside: true } 

Everything works as expected, the this in the hello() method has the correct scope. But, when I make a new instance of the class and export just hello of this new instance:

// Class.js
class Test {
  constructor() {
    this.inside = true;
  }

  hello() {
    console.log('inside hello')
    console.log(this);
  }
}

module.exports = (new Test()).hello; // <- just hello is exported

then the scoping of the hello() changed and it seems it is not a part of the class anymore:

// index.js
const hello = require('./index.js');

hello();
// -> 'inside hello'
// -> undefined

Is there a reason, why this single exported function acts so differently?


I tried it in Python, and it worked (maybe it does in other languages as well):

# Class.py
class Class:
  def __init__(self):
    self.test = 'hello'

  def hello(self):
    print('inside hello')
    print(self)

hello = Class().hello


# index.py
from Class import hello

hello()
# -> 'inside hello'
# -> <Class.Class instance at 0x10e26e488>
Jan Peer
  • 182
  • 2
  • 7
  • 1
    `this` is always the object on which the function is called. You call `hello` directly so `this` is undefined. – t.niese Apr 27 '18 at 07:24
  • I believe you might not be exporting a method only but a instance of an object with that method only. – Muhammad Usman Apr 27 '18 at 07:24
  • 1
    Unlike most languages, `this` in Javascript is not passed with methods,.. In it's simplest form if you don't use a `.` (dot) to call your function, Javascript has no way of knowing it's this context,.. This is were bind / call etc come into play. – Keith Apr 27 '18 at 07:25
  • Possible duplicate of [How does the "this" keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – t.niese Apr 27 '18 at 07:26
  • there is a specificity of NodeJs here, in a browser, the context would have been the global `this` which is `window`. Node behaves differently in term of global stuff. Also, `this` in JS comes from execution context, not creation, it depends from where it's called, if not bound – Kaddath Apr 27 '18 at 07:30

2 Answers2

2

When you call hello() standalone, it has no calling context - it's not being called from an object, when said object would ordinarily be its calling context. (such as Test.hello(); - the calling context would be Test in that line)

If you want to bind its calling context so that it's usable as a standalone function, you should export the bound function, such as:

const test = new Test();
module.exports = test.hello.bind(test);
CertainPerformance
  • 260,466
  • 31
  • 181
  • 209
1

They have different context:
In first case, "hello" binds to "Test" object.
In second one, "hello" binds to "global scope" which is "undefined".
If you run second one in web browser, you will get "window" object which is the global context in browser.

zoly01
  • 117
  • 2