I have a generic question about javascript specification or implementation of functions pointer (delegates?) which are points to object methods.
Please, read the following code snippet. Here we have an object with a method using 'this' to access an object field. When we call this method as usual (o.method();
), returns value of the specified field of the object. But when we create pointer to this method (callback) and invoke it, returns an undefined value, because 'this' inside method's scope now is global object.
var o = {
field : 'value',
method : function() {
return this.field;
}
};
o.method(); // returns 'value'
var callback = o.method;
callback(); // returns 'undefined' cause 'this' is global object
So, where is my 'this'?
"this" is late binding. that is, it gets bound to a thing just before the function is executed. What it is bound to depends on how you call your function.
if you call it like (function invokation):
myfunction();
"this" is bound to the global object
if you call it like (method invokation):
myobject.myfunction();
"this" gets bound to "myobject"
you can also call it like so (call invokation):
myfunction.call(myobject);
in which case "this" gets bound to myobject
there is also (constructor invokation):
new MyFunction();
in which "this" gets bound to a newly constructed blank object whose prototype is MyFunction.prototype.
this is how the creators of javascript talk about it, anyway. (and I think it is discussed this way in the spec) Different ways of invoking a function.
the new version of the ecmascript standard (ecmascript5) includes the prototype library's "bind" method, which returns a new function with "this" prebound to something you specify. for instance:
mynewfunction = myfunction.bind(myobject);
mynewfunction();
the invokation of mynewfunction has "this" already bound to myobject.
You can specify the context of this
for example when you call a method through the .apply()
or .call()
methods. In your case, like you said, the context has changed. If you really need to make field
be o.field
, you have to tell explicitly so, for example by using a closure when defining your method
method.
You're right it wasn't valid javascript. I was thinking of using new function which allows you to have multiple instances:
function o2(value) {
var _this = this;
this.field = value;
this.method = function() {
return _this.field;
};
}
var test1 = new o2('blah');
var test2 = new o2('meh');
var callback1 = test1.method;
var callback2 = test2.method;
alert(callback1());
alert(callback2());
Alternatively if you want to continue using a singleton you can reference o from within the object.
var o = {
field : 'value',
method : function() {
return o.field;
}
};