0

I didn't understand the var self = this; in the below code. I know that "The value of this, when used in a function, is the object that "owns" the function.".Then this keyword inside the object's function refer to that object,right?However the comments of below codes says the opposite of that.

I'm confused about why we cannot use this keyword inside an object's function, in the below code? What does this refer to in below codes?

var util = require('util');
var EventEmitter = require('events').EventEmitter;

// @station - an object with `freq` and `name` properties
var Radio = function(station) {

    // we need to store the reference of `this` to `self`, so that we can use the current context in the setTimeout (or any callback) functions
    // !!!! -> using `this` in the setTimeout functions will refer to those funtions, not the Radio class
    var self = this;

    // emit 'close' event after 5 secs
    setTimeout(function() {
        self.emit('close', station);
    }, 5000);

    // EventEmitters inherit a single event listener, see it in action
    this.on('newListener', function(listener) {
        console.log('Event Listener: ' + listener);
    });
};

// extend the EventEmitter class using our Radio class
util.inherits(Radio, EventEmitter);

// we specify that this module is a refrence to the Radio class
module.exports = Radio;

I read similar posts and understood, however i couldn't understand the comments of below codes. Also, nobody mentioned about the this keyword inside a function's function argument inside a constructor. Especially the second sentence which is written bold makes me confused totaly :

We need to store the reference of this to self, so that we can use the current context in the setTimeout (or any callback) functions. using this in the setTimeout functions will refer to those funtions, not the Radio class

Quoted from : http://www.hacksparrow.com/node-js-eventemitter-tutorial.html

metis
  • 757
  • 8
  • 22
  • 1
    *"The value of this, when used in a function, is the object that "owns" the function."* - Nope. The [value of `this`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this) depends on how the function is called. – nnnnnn Jun 18 '16 at 22:02
  • Is it wrong? I quoted it from http://www.w3schools.com/js/js_function_invocation.asp . – metis Jun 18 '16 at 22:03
  • 1
    @metis yep, it is incorrect (or their use of "owns" is misleading). And now you see how w3school is a terrible resource to learn from. – zerkms Jun 18 '16 at 22:04
  • 1
    It is not entirely precise. Better would be: *"`this` within a callback function passed to `setTimeout` will represent the `window` object, because it is the browser that will call that callback once the time-out occurs."* – trincot Jun 18 '16 at 22:05
  • That w3schools page has over-simplified it, explained even the simplified version badly, and has nonsensical examples for `.call()` and `.apply()`. Also, objects don't really "own" functions: they may have "methods" that are properties that *reference* functions, but you can create other references to the same functions. – nnnnnn Jun 18 '16 at 22:05
  • Never, I said never, use *w3fools* as a point of reference. – melancia Jun 18 '16 at 22:07
  • Yeap. I read from some resource 'The value of this depends on how the function is called.' . Now i remembered and understood the logic. However i still couldn't understand my question, why this keyword inside an object's function does not refer to that object, and why we have to use var self = this; ? Can you give a sample explaining it and showing that this refers to different contexts for above example? – metis Jun 18 '16 at 22:09
  • In your example, the function that actually uses `self` isn't a method of any particular object, it's just an anonymous function passed to `setTimeout()`. (But again, even if it did "belong" to an object, the value of `this` depends on how the function is called.) – nnnnnn Jun 18 '16 at 22:11
  • @nnnnnn, a function usually does not belong to a particular object, and that it is anonymous has no bearing on it. Even it you write `setTimeout(myobj.myfunc, 100)`, the function passed to `setTimeout` does not belong to `myobj`. The exception is when a function is explicitly bound to a certain object that will have the role of `this`, with `bind`. – trincot Jun 18 '16 at 22:14
  • Possible duplicate of [How does the "this" keyword work?](http://stackoverflow.com/questions/3127429/how-does-the-this-keyword-work) – trincot Jun 18 '16 at 22:18
  • @trincot - Yes I know. I said in an earlier comment that objects don't own functions. I was just pointing out that the function in question here isn't even associated with any objects, so even the incorrect belief that `this` is always a function "owner" wouldn't apply here anyway. – nnnnnn Jun 18 '16 at 22:21
  • Assume that i don't know that rule and i used this keyword in the above example inside the object's function. How it fails? Can you show me an example that this keyword inside the object's function refer to somewhere? – metis Jun 18 '16 at 22:23
  • 1
    @metis, if you would have written `this.emit('close', station);` you would get a runtime error saying that `this.emit` is not a function. This is because at that moment `this` is `window` (as explained above). – trincot Jun 18 '16 at 22:33
  • I understood . In either case, the comment " using 'this' in the setTimeout functions will refer to those funtions, not the Radio class" is incorrect, because this keyword does not refer to functions, it refers to objects. Right? – metis Jun 18 '16 at 23:31

2 Answers2

1

The value og the this keyword will change value based on the current context. The complete description of how this works is somewhat complicated. See MDN for more details.

In your case, this will have a different value when the anonymous function inside the setTimeout call is eventually called. However, the self variable will still be available.

kentis
  • 61
  • 4
0

The purpose of 'this' in a function is a reference to the object that called the function. Since you're passing an anonymous function to the window with setTimeout, any 'this' call within that function will be referencing the window object.

You could use the Javascript Bind function to preserve the context of 'this' within the callback function regardless of where it's called.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Your setTimeout function would look like this:

setTimeout(function() {
    this.emit('close', station);
}.bind(this), 5000);
Michael Lyons
  • 554
  • 3
  • 9
  • *"The purpose of 'this' in a function is a reference to the object that called the function"* - It would be more accurate to say that `this` refers to the object that the function is supposed to operate on (assuming the purpose of the function relates to an object at all), and it could be set to *any* object depending on how the function is called. – nnnnnn Jun 18 '16 at 22:51