1

I would have thought that console.log(myCounting.value); would actually print 7 because the add method got invoked twice (see comments) . However it prints 6. Is that because of the scope? Meaning that invoking the 'invoking' function with myCounting.add doesn't change the value because its a different scope? Could someone explain as I'm learning scopes..Thanks!!

function Counting(){
  this.value = 5;
}

Counting.prototype.add = function(){
  this.value++;
}

var myCounting = new Counting();
myCounting.add();   // invoked once

function invoking(funcs){
  funcs();
}

invoking(myCounting.add); //invoked twice
console.log(myCounting.value);
Anthony E
  • 10,363
  • 2
  • 20
  • 42

2 Answers2

2

It doesn't really have that much to do with scope (except that functions create scope maybe?). It has everything to do with how this works.

The value of this depends on how the function is called. There are a handful of ways a function could be called, each can result in a different value for this. In your example, myCounting.add() and func() are different ways of calling a function, resulting in different values for this, and hence this.value++ will be applied to two different objects.

See How does the “this” keyword work? and maybe How to access the correct this / context inside a callback? for more information.

Community
  • 1
  • 1
Felix Kling
  • 705,106
  • 160
  • 1,004
  • 1,072
  • Thank you. As I understand, this refers the caller. How then in this following example, this does NOT refer to the object? var name="j"; var myObject={ name:"x", property:{ name:"y", getFull:function(){ return this.name; } } }; var fullname=myObject.property.getFull; fullname(); – learningcoding May 24 '16 at 01:14
  • *"As I understand, this refers the caller."* That's not correct (but I guess that depends on what you mean by "caller"). Only a function can be the caller of another function. In that sense, `this` doesn't refer to the caller. The reason why `this` doesn't refer to the object in your other example is that you are calling the function as `fullname()`. When a function is called this way, `this` refers to the global object or is `undefined` in strict mode. How the function was defined doesn't matter. Functions are first class citizens in JavaScript and they are not automatically bound. – Felix Kling May 24 '16 at 01:17
  • `this` refers to the object to the left of the last dot that's to the left of the method name, like _y_ in `x.y.z()`. if there is nothing to the left, then it's the same as _window_:`window.y()`'s `this` == `y()`'s `this` – dandavis May 24 '16 at 01:29
1

Unfortunately, in Javascript the value of this evaluates differently depending on how/where the function is called:

In your first example:

myCounting.add()

this refers to the calling object of the add function, which in this case is your myCounting instance, as you expect.

In your second example:

invoking(myCounting.add)

Here, add is bound to the top-level window object (if called from within a browser) since it's being called from the top-level scope. Accordingly, this is actually the global window object.

The result is the same as if you called this.value++ directly from your browser console. Since this.value is undefined the result of this.value++ is (nonsensically) NaN.

Anthony E
  • 10,363
  • 2
  • 20
  • 42
  • "*add is treated like a globally declared function and bound to the top-level window object* no it's not. Its *this* is set to the global object because it was not set by the call. Where the object was created or called from is irrelevant (except for arrow functions), *this* is set by how the function is called (or use of *bind*). – RobG May 24 '16 at 01:08
  • This is more of a semantic distinction, though I agree the wording here can be construed to make it seem like the value of `this` depends on where the function is defined, which is not generally the case. I've updated my answer to make it more clear. – Anthony E May 24 '16 at 01:17
  • The second last paragraph is still misleading. – RobG May 24 '16 at 03:14