0

I wrote the following code, where I would expect the calls to getFull() and useGetFull() to do the same thing, since useGetFull just gets a function object for getFull() and calls it.

function Person(name, family) {
    this.name = name;
    this.family = family;
}

Person.prototype.getFull = function() {
    console.log(this.name + " " + this.family);
};

Person.prototype.useGetFull = function() {
    const f = this.getFull;
    f();
    // f.call(this) works as expected
}

p = new Person("Bob", "Smith");
p.getFull();
p.useGetFull();

However, they don't do the same thing, because inside useGetFull(), "this" is the global object. I noticed that using f.call(this) instead of f() works as intended, but I can't wrap my head around why I have to use it. Why is the value of "this" different depending on how/where I call the function?

busfahrer
  • 213
  • 1
  • 6
  • I always avoid using 'this' in javascript when I can because I know pitfalls like this happen. :( – TKoL Sep 09 '17 at 09:12
  • Possible duplicate of [How does the "this" keyword work?](https://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – Andreas Sep 09 '17 at 09:14
  • Inside of 'useGetFull' you can also try this: `const f = this.getFull.bind(this);` – TKoL Sep 09 '17 at 09:14

2 Answers2

1

A simple rule:

a.b() //b called with context a
d.e() //e called with context d
c() // c called with no context ( so the global instead)

Javascripts context depends on how the function was called.

Jonas Wilms
  • 106,571
  • 13
  • 98
  • 120
1

If you haven't noticed, this.getFull() also works. This is because when you invoke the function as a property of an object (any object), that function's this will refer to that object, the object you invoked the function on, in case of foo.bar(), foo, and in case of this.getFull(), this. This is why this example works as expected:

function Person(name, family) {
    this.name = name;
    this.family = family;
}

Person.prototype.getFull = function() {
    console.log(this.name + " " + this.family);
};

Person.prototype.useGetFull = function() {
    /* getFull is preceded by something, it is invoked through "this", so 
    the "this" reference inside of getFull will be set to the "this" part in 
    the statement "this.getFull()". */
    this.getFull();
}

p = new Person("Bob", "Smith");
p.getFull(); prints out Bob Smith
p.useGetFull(); // prints out Bob Smith


However, when a function is invoked not as the property on an object, in other words, when it is not accessed in a way similar to either foo.bar() or foo["bar"](), but in a way like foo(), even if foo is a reference to a variable whose value is x.y, like f() in your example, its this will be bound to the global object, in a browser, that object is window.

function Person(name, family) {
    this.name = name;
    this.family = family;
}

Person.prototype.getFull = function() {
    console.log(this.name + " " + this.family);
};

Person.prototype.useGetFull = function() {
    const f = this.getFull;
    /* this call is not preceded by any objects, it is a plain 
       traditional function call, it is a function invokation in its 
       simplest form. all functions invoked in this manner will have 
       their "this" reference set to the global object. */
    f();
}

p = new Person("Bob", "Smith");
p.getFull();
p.useGetFull();


If you are interested in this (pun not intended), go here.

doubleOrt
  • 2,149
  • 10
  • 26