0

My question is pretty straight forward, but I can't find an answer anywhere (maybe my search terminology isn't correct, but here goes)...

Why is it that I can do the following:

var _Class = function(){
    this.output = "Hello";
}

var Class = new _Class();

Class.Talk = function(){
    console.log(this.output);
}
Class.Talk(); // outputs "Hello"

And this:

var func = function(){
    console.log(Class.output);
}
func(); // outputs "Hello" 

However I can't do:

var _Class = function(){
    this.output = "Hello";
}

var Class = new _Class();

Class.Talk = function(){
    console.log(this.output);
}

var func = Class.Talk;
func(); // undefined

I thought that this is meant to store a reference to the original function?

Zze
  • 15,599
  • 9
  • 68
  • 98
  • `Class.talk` will only exist for that instance. use `_Class.prototype.$x` to get it be around for all instances of `_Class` – Ryan McCullagh May 27 '16 at 00:54
  • 1
    What do you expect `this` to refer to in `func()`? It seems you should read https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/this . – Felix Kling May 27 '16 at 00:55
  • You've been waiting for that huh @self! – omarjmh May 27 '16 at 00:55
  • @FelixKling I was expecting to have created a pointer to the class? – Zze May 27 '16 at 00:55
  • @JordanHendrix not sure what you mean – Ryan McCullagh May 27 '16 at 00:56
  • When you call a function as `f()`, then `this` refers to the global object or `undefined`. "Methods" are not automatically bound. – Felix Kling May 27 '16 at 00:57
  • @FelixKling So there is no level of inheritance / polymorphic principles in JS? – Zze May 27 '16 at 00:59
  • Why are you asking about prototype functions in the title but not using any in your code? – Bergi May 27 '16 at 00:59
  • 2
    Sure there is. But you are calling the function "incorrectly". You are not calling the function as a method of an object. See the MDN documentation about `this`. – Felix Kling May 27 '16 at 01:01
  • @FelixKling Ahhhhhhhhhhhhhhhh I see. Interesting. – Zze May 27 '16 at 01:04
  • `this` is determined at execution unless you're using the arrow functions, which is a lexical `this`. Since you have removed the implicit binding of the method from its object, `this` points to the global object. There is no `output` property on the global object, hence `undefined` is returned. – timolawl May 27 '16 at 01:06
  • @Bergi I thought that this was a valid way of defining prototypes? Or were you referring to the Talk function specifically ? – Zze May 27 '16 at 01:07
  • @Zze: Nope, you didn't use prototypes. `_Class` is a *constructor* if that is what you mean. To use the prototype, you'd have written `_Class.prototype.Talk = function(){…}` – Bergi May 27 '16 at 01:10
  • @Zze: And btw, you really shouldn't name that variable "Class" when it's an instance. Which also should be lowercased (only constructor names are capitalised). – Bergi May 27 '16 at 01:11
  • @Bergi Ass, I think I have used the wrong terminology here (apologies all). Normally I wouldn't, but the actual class I have I use it as if it were a static class, and only gets instantiated the once. – Zze May 27 '16 at 01:13
  • 1
    @Zze: In that case, drop the class/constructor and use an object literal instead. Also [you don't need to use `this` at all](http://stackoverflow.com/a/10711164/1048572). – Bergi May 27 '16 at 01:18
  • Damn it @Bergi ... That link has just made me want to re-write thousands of lines of code. You have been incredibly helpful. Thank you! – Zze May 27 '16 at 01:23

1 Answers1

1

If you do func.apply(Class) it will work because you're telling it to use the context of Class. The context of the function body when you do the assignment is window, so that's why you're seeing undefined

Ryan McCullagh
  • 13,581
  • 8
  • 56
  • 101