2

I'm trying to figure out how to get the function context from a constructor to one of it's prototype functions. But when I check the 'this' value in the prototype function, it just shows it as 'Object' and not the calling (ctor) context.

So I have code:

function CL(){
    ...
    (stuff)
    ...
    console.log(this);
    protoFunc(this);
}

CL.prototype.protoFunc = function(context) {
  var self = context;
  console.log(context);
  ...
}

The function context before calling protoFunc is that of CL. But in protoFunc it is [Object object].

How do I get the function context into protoFunc?

Thanks.

Les

RobG
  • 142,382
  • 31
  • 172
  • 209
Les
  • 487
  • 1
  • 10
  • 22
  • So you want to dictate `this` inside `protoFunc`? – Jon Oct 02 '13 at 21:21
  • 1
    Does your code work, how would you call `protoFunc(this)`? it should be `this.protoFunc(this)` or rather you dont need to pass the context at all, just access it with `this` inside the `protoFunc ` – PSL Oct 02 '13 at 21:21
  • This has got to be simplified example code. It can't actually work. – rescuecreative Oct 02 '13 at 21:25
  • Please provide a fiddle where you can replicate this issue. It seems like there are lots of information that are hidden and that could be causing the behavior that you are describing. – PSL Oct 02 '13 at 21:29
  • The code 'works' in the sense that there is not error. But obviously it isn't working because of the context issues. Within protoFunc (and other prototype functions), there are references to variables defined in the ctor. But there are errors when trying to reference them. Hence the question of how to get the context to them. – Les Oct 02 '13 at 21:31
  • Please note that a function's *this* value is set entirely by how the function is called or by using [*bind*](http://www.ecma-international.org/ecma-262/5.1/#sec-15.3.4.5). The term "context" is associated with [*execution context*](http://www.ecma-international.org/ecma-262/5.1/#sec-10), of which the *this* keyword is but one parameter. – RobG Oct 02 '13 at 22:20
  • You don't have to pass `this` to that function but have to call it like: `this.protoFunc` on your prototype in that way, here is a detailed explanation what `this` could be: http://stackoverflow.com/a/19068438/1641941 And here is something about prototype, inheritance, overriding and calling super: http://stackoverflow.com/a/16063711/1641941 – HMR Oct 03 '13 at 03:55

3 Answers3

3

You can't call protoFunc like that, you need this in front. Aren't you getting an error? The code should be:

function CL(){
    ...
    (stuff)
    ...
    console.log(this);
    this.protoFunc();
}

This will give you the correct this inside the prototype method - provided CL is properly called with new:

var instance = new CL();
bfavaretto
  • 71,580
  • 16
  • 111
  • 150
  • That is what even i doubted first but the post says `But in protoFunc it is [Object object].` – PSL Oct 02 '13 at 21:23
  • @PSL True, maybe the OP forgot to use `new`. Updated the answer to point that out. – bfavaretto Oct 02 '13 at 21:25
  • That confused me again because he says `The function context before calling protoFunc is that of CL` so it can't happen without a `new` Probably he is doing something else as well `protoFunc` being called as a call back in the hidden portion of OPs code which he is not showing us. – PSL Oct 02 '13 at 21:27
  • @PSL I'm sure the OP is more confused than either of us. All I can do is post an example that works, I'm not sure about how the actual code looks like... – bfavaretto Oct 02 '13 at 21:29
  • The instance of CL is created in a – Les Oct 02 '13 at 21:35
  • @Les There must be something else relevant going on. Here is a jsfiddle showing what I mean: http://jsfiddle.net/ky5PV/ – bfavaretto Oct 02 '13 at 21:40
  • @bfavaretto Sorry, I'm not 'jsfiddle' knowledgeable. How do I get the JS to run on its own? Or is this just meant to be sample code? – Les Oct 02 '13 at 21:54
  • @Les There is a "Run" button on the left side of the top bar. – bfavaretto Oct 02 '13 at 21:57
  • @bfavaretto Sorry. Forgot to bring up the console! Your code worked, but I've done that exact thing and it goes nowhere. Just reports [object Object]. – Les Oct 02 '13 at 22:08
  • @Les As I said, there must be something else going on on your real code. The problem is how to find what it could be... – bfavaretto Oct 02 '13 at 22:10
1

You shouldn't even need to do that. Try this:

function CL(name) {
  //for example...
  this.name = name;
}

CL.prototype.protoFunc = function () {
  console.log(this);
};

Then you would have to instantiate an object with your constructor...

var x = new CL('Bob');
x.protoFunc();
//=> logs {name: 'Bob'}

If you are trying to get the ACTUAL CONSTRUCTOR FUNCTION into your method, you shouldn't need any tricks there either.

CL.prototype.protoFunc = function () {
  var cTor = CL;
  console.log(cTor);
};

Is that what you're looking for or are you trying to get something else?

EDIT:

If you want to call the prototype function from within the constructor, you should do something like this:

function protoFunc() {
  console.log(this);
}

function CL(name) {
  protoFunc.call(this);
}

CL.prototype.protoFunc = protoFunc;
rescuecreative
  • 3,607
  • 3
  • 18
  • 28
  • That's right. I was a little unclear about what specific object you wanted to pass to your prototype function. If you want to call the prototype function from within the constructor, it will have to be defined before it is placed into the prototype. See my edit. – rescuecreative Oct 02 '13 at 21:38
  • So, you can't get the value [object Object] unless the toString method is being called on it. Do you have a call to toString that you're not showing here? If you're not doing it one if two things is happening. Another function is calling it and you don't realize it or you're in a weird browser that is doing it when it shouldn't be. My tests are done in Chrome and I don't get that. I'm not sure what you'd get in IE. What platform are you testing on? – rescuecreative Oct 02 '13 at 22:44
  • I was trying to answer my own question but there is a timer running on people with low scores :-) Anyway, it turns out that there wasn't a problem technically. The problem I was observing was in trying to observe the context. I was using console.log statements, but inside of functions I would put in some identifying text e.g., console.log("in func, self = " + self);. Turns out that helpful text was not so helpful. That text took the true context and reduced it to [object Object]. Probably something to do with concatenation. Thanks to all for your help. – Les Oct 03 '13 at 00:25
  • @Les if you get [object Object] in your browser when you console.log an object you are using the wrong browser, try firefox (control + shift + K) and click on [object Object] to see what it is or install firebug plugin and press F12 to open the console. Or use Chrome and press F12 to open the console. Both firebug and Chrome will give you detailed information about the object you're logging so you don't have to guess what it is (95% of variables in JS are [object Object]) – HMR Oct 03 '13 at 04:02
  • It's not that. Note Les' comment. He was adding the object to a string in his console log call thus causing an unintended type coercion. – rescuecreative Oct 03 '13 at 12:11
1

A function's this value is set either by how the function is called, or by using Function.prototype.bind.

Given:

function CL(){
    console.log(this);  // a new object
    protoFunc(this);  // protoFunc doesn't exist on CL's scope chain and will throw an error
}

If CL is called as follows (and assuming bind hasn't been used):

CL()

its this value has not been set, so on entering the function in non–strict mode it will be set to the global (window) object. In strict mode it will be undefined.

If CL is called using new:

var cl = new CL()

then this within the function will reference a new Object created as if by new Object(), i.e. it's a reference to the instance. Since this new object is returned by default and here it is assigned to cl, then a reference to the constructor function's this has been kept, there is no need to keep any other reference.

Note that each call to CL creates an entirely new execution context.

If you create an instance of CL and then call a method assigned to the constructor's prototype like:

cl.protoFunc()

then this within protoFunc will be cl.

Your statement:

The function context before calling protoFunc is that of CL

doesn't make sense, presumably here you are confusing "context" with "this". As noted above, this is set by the call (or bind), so you have to show how you're calling CL to determine what ist this will be.

How do I get the function context into protoFunc

Given that this in the constructor is the instance and that a function's this value is set by the call:

cl.protoFunc()

will do the job.

Context

The term "context" has crept into ECMAScript jargon as a pseudonym for this, which is unfortunate. ECMA-262 defines execution context essentially as an environment created when entering a function (or a new global environment or when using eval) that includes the scope chain and all variables of the function, including its this value. You can't reference an execution context or access it in any way.

So a function's context is much more than just this.

RobG
  • 142,382
  • 31
  • 172
  • 209
  • Thanks Rob for a detailed answer, I used to call it context and then called it invoking object as it's the object invoking the function. – HMR Oct 03 '13 at 04:09