What object javascript function is bound to (what is its "this")?
Partial Application
You can do partial application:
// This lets us call the slice method as a function
// on an array-like object.
var slice = Function.prototype.call.bind(Array.prototype.slice);
function partial(f/*, ...args */) {
if (typeof f != 'function')
throw new TypeError('Function expected');
var args = slice(arguments, 1);
return function(/* ...moreArgs */) {
return f.apply(this, args.concat(slice(arguments)));
};
}
What Object is this Function Bound To?
Additionally, there's a pretty straight-forward solution to the first part of your question. Not sure if this is an option for you, but you can pretty easily monkey-patch things in JS. Monkey-patching bind
is totally possible.
var _bind = Function.prototype.apply.bind(Function.prototype.bind);
Object.defineProperty(Function.prototype, 'bind', {
value: function(obj) {
var boundFunction = _bind(this, arguments);
boundFunction.boundObject = obj;
return boundFunction;
}
});
Just run that before any other scripts get run, and any script which uses bind
, it will automatically add a boundObject
property to the function:
function f() { }
var o = { };
var g = f.bind(o);
g.boundObject === o; // true
(Note: I'm assuming you're in an ES5 environment above due to the fact that you're using bind
.)
A function in javascript is not technically bound to anything. It may be declared as a property of an object as in:
var obj = {
fn: function() {}
}
obj.fn();
But, if you get the function into it's own variable by itself, it is not bound to any particular object.
For example, if you did this:
var obj = {
fn: function() {}
}
var func = obj.fn;
func();
Then, when you call func()
which in turn executes the fn()
function, it will have no association with obj
at all when it is called. Associating an object with a function is done by the caller of the function. It is not a property of the function.
If one were to use fn.bind(obj)
, that creates a new function that just internally executes a call to obj.fn()
. It doesn't magically add any new capabilities to javascript. In fact, you can see a polyfill for .bind()
to see how it works here on MDN.
If you are expecting this
to always be a particular object no matter how a function is called, that is not how javascript works. Unless a function is actually a shim that forces an association with a hard-wird object when it's called (what .bind()
does), then a function doesn't have a hard-wired association. The association is done by the caller based on how it calls the function. This is different than some other languages. For example, in C++, you can't call a function without having the right object to associate with it at call time. The language simply won't resolve the function call and you get a compile error.
If you are branching on types in javascript, then you are probably not using the object-oriented capabilities of the language properly or to your best advantage.
Instead of binding the function func
to the objects, why not try treating func
as an object, that can hold obj1 and obj2 as its properties?
For example:
var func = function {
this.object; // Could be obj1 or obj2
return this.f === arguments.callee;
// => true, if this.object is not null
}
var f = func;
f.object = obj1; // or func.object = obj2;
You can also write a function that handles whether or not the object is obj1 or obj2:
function g(f) {
if (typeof(f) !== 'function') throw 'error: f should be function';
if (f.object === obj)
// this code will run if g(f) was called
doSomething(f);
if (f.object === obj2)
// this code will run if g(f) or g(bound) was called
doSomethingElse(f);
}
The reason is that you want to treat obj1 and obj2 as a property of the function f
. However, when you bind, you are adding the function as a property of either obj1 or obj2. It's possible to bind the function to multiple objects, so it doesn't make sense to look for THE one object to which you bound the function; because you're adding the function as a subset of the object.
In this case, since you want to treat the object as a subset of the function, it might make sense to add a property into the function that can hold obj1 or obj2.