5

I know how to use the methods for changing the context of a function/method call: apply, bind, call. My question is this, is there a way to check if a function/method has already had its context set?

// given
var beta;

function alpha () {
  return this;
}

function isContextSet (fn) {
  /* check for context binding on fn */
}

beta = alpha.bind("hello");

isContextSet(alpha); // returns false
isContextSet(beta); // returns true

I think I know the answer to this already but thought I would ask anyway, if for no other reasons than: 1. confirm my assumption, or 2. learn something. I'm sure that I am not the first to ask this question but I have had no idea on how to actually find an answer since all I get are responses to how to use: .apply(), .call(), or .bind().

6
  • 1
    Maybe this helps: What object javascript function is bound to (what is its “this”)?. Commented Jun 22, 2013 at 13:40
  • 2
    "has already had its context set" What do you mean by "already"? .apply(), .call() and .bind() don't permanently set this for every time the function gets called (noting that .bind() returns a new function that permanently has a specific this, but doesn't actually change the original function). Every possible way to call a function sets this to something - it's just some ways do it implicitly, some do it explicitly... Commented Jun 22, 2013 at 13:44
  • I added some code to show what I am try to get at. I understand how the three methods work, and I know how to check the context of a function/method while inside the body of the invocation. How do you check the context from outside the invocation, as I have shown above? I can't think of a way to do it at all in JS. Commented Jun 22, 2013 at 13:46
  • 1
    In that case you should really look the question I linked to. It appears to be the same. Commented Jun 22, 2013 at 13:58
  • 1
    Felix Kling, you posted a great resource. I read through it, and it has a great suggestion. But I think that it is only solving a portion of the problem; albeit very well. I think what I am looking for is something that is of such minor importance that it isn't worth doing really since there would always be a way around it. There is no need to spend time attempting to solve such an edge case in this instance. This has been a great discussion though. Thank you everyone for joining in. Commented Jun 22, 2013 at 14:01

3 Answers 3

3

No.

Actually, it's incorrect to refer to binding as "changing" the context. What it does is transform one function into another one which calls the first with a particular context.

Functions can be bound in many ways. For instance, I could bind it myself:

function bind(fn,ctxt){
    return function(){
        fn.apply(ctxt,arguments);
    };
}

Or, I could bind it with Function.prototype.bind, or a shim that does the same thing, or underscore's _.bind. I could bind it to initial arguments in addition to the context. In each case, there's no way to tell what has happened without essentially actually executing the function.

Binding is just one of many ways to transform one function into another one. I could also transform a function to execute one second from now, or be executed twice. There is nothing magic about binding; it just creates a new function based on the old one. There is no special variable called [[bound_to]] set on the function that you might be able to examine (unless you use your own custom implementation of bind, as another answer suggests). There's no post facto way to determine how the function was transformed.

The closest I can imagine coming is checking the possibly bound function against an unbound version and see if they are equal.

function log_this(){console.log(this);}
var bound_func=log_this.bind(my_var);
console.log(log_this===bound_func); // FALSE
Sign up to request clarification or add additional context in comments.

1 Comment

I think you summarize this pretty well. I agree that there is no way to truly test the context, as I am defining above. JavaScript simply provide too many ways to get around the situation I am attempting to test for.
0

What could be done is something like this:

function f(context, whatever) {
    if(this !== context) {
        //context has been changed
    }
}

var y = f.bind(thingy);
y(otherThingy, something);

You could also have a custom bind function and have a sort of a hack like this:

function bind(func, context) {     
    var newFunc = func.bind(context);
    newFunc._this = context;
    return newFunc;
}

function checkContext(func, context) {
    return func._this !== context;
}

1 Comment

And here's a fiddle demonstrating my own version of a custom bind function, which I was about to post as an answer when I saw you'd already covered it with a similar idea: jsfiddle.net/jx4fY
-1

I think this is interesting question for those how love JavaScirpt and I hope this is response what you are looking for:


var isContextSet = function (fn) {
   var testThis = {}; //unique object for testing what is this inside fn
   return fn.call(testThis) !== testThis;
}

I try to "set" this inside fn: fn.call(testThis); and if that function returned reference to newly created object (testThis) then it is not binded. I hope you get it :)

EDIT: This works when fn retuns this (as shown in question). Otherwise you can not define isContextSet properly.

2 Comments

What if the function does not return this; but an other value or no value at all? This will generated many false positives. Simplest example: isContextSet(function() {}) will yield true, even though the function is not bound to a specific value.
In question example function returns this. But if it doesn't then you are right. I guided from question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.