Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Javascript - using apply to call a bound function

Tags:

javascript

Say we have the following sample Javascript code:

var modeller = "foo";
var provider1 = function (modeller, content, optionalArg) {
    alert("this: " + this + ", content: " + content + ", optionalArg: " + optionalArg);
}.bind(null, modeller);

var provider2 = function (content, optionalArg) {
    alert("this: " + this + ", content: " + content + ", optionalArg: " + optionalArg);
};

var createConsumer = function () {
    // some arbitrary private vars
    var content = 1; 
    var option = 2; 

    var doConsume = function(provider) {
        provider.apply(this, [content, option])
    };
    return {consume: doConsume};
};

// Now use them
var consumer = createConsumer();

consumer.consume(provider1);
consumer.consume(provider2);

This is simplified a lot for demo purposes, but the gist is that provider1 is already bound, and provider2 is not - the consumer cannot pass itself as the this argument for provider1.

The questions: Is there a way to detect this kind of case where a function is already bound? Is there a way to get provider1 to use the consumer as this? Assuming the answer is no, what is the best way to work around this sort of situation?

like image 401
Krease Avatar asked Jan 19 '26 20:01

Krease


2 Answers

"Is there a way to detect this kind of case where a function is already bound?"

No.

"Is there a way to get provider1 to use the consumer as this?"

No.

"...what is the best way to work around this sort of situation?"

Since it seems like you want to bind an argument but not the this value, I would make an argument binder method on Function.prototype that returns a function with only the arguments bound, and not this.

Function.prototype.argBind = function() {
    var _slicer = [].slice,
        orig_args = _slicer.call(arguments),
        orig_func = this;
    return function() {
        return orig_func.apply(this, orig_args.concat(_slicer.call(arguments)));
    };
};

Then you'd use it like this:

var modeller = "foo";
var provider1 = function (modeller, content, optionalArg) {
    alert("this: " + this + ", content: " + content + ", optionalArg: " + optionalArg);
}.argBind(modeller);

Now the provider1 function will be invoked with whatever normal this value is given, but the modeller will be bound as the first argument.

like image 189
I Hate Lazy Avatar answered Jan 22 '26 10:01

I Hate Lazy


There is a way to detect if a function is already bound but it's not really elegant: /\[native code]/.test(foo.toString()); Bound functions have native code as toString(). This works for Chrome(NodeJS). I don't know about other browsers.

like image 42
Mihai Voicescu Avatar answered Jan 22 '26 09:01

Mihai Voicescu