3

There is something I don't understand in javascript and broke down a sample problem to an essential case:

    a = function () {
      this.b = 5;
    }

    a.prototype.c = function () {
      alert(this.b);
    }

    var d = new a();
    var e = d.c; // how do I save a ref to the method including the context (object)??

    d.c(); // 5 -> ok
    e();   // undefined -> wtf??

So why is the function being called without its context in the last example? And how can I call it with the context?

Thanks in advance :-)

3 Answers 3

6

d.c is like an unbound instance method. You can use Function.prototype.bind to create a new function that's bound to d (the first argument to .bind is the this argument):

var e = d.c.bind(d);

Or call e with d as the this argument:

e.call(d);
Sign up to request clarification or add additional context in comments.

Comments

2

You need to call the method using the object to get the context right. So:

var e = function() { return d.c(); };

In newer browsers you can use the bind method to do the same:

var e = d.c.bind(d);

In jQuery for example there is the proxy method that you can use also in older browsers:

var e = $.proxy(d.c, d);

Comments

1

It's about resolving the this value. This is resolved in the following way:

myObject.something();//this in something is myObject
window.something();//this is window
button.onClick=function();//this when button is clicked is button

How to solve it is already given, it's a common pitfall with passing callbacks like in the following example using setTimeout

var test = function () {
  var me = this;// set reference to this
  this.sayAgain=function(){
     console.log("Hi, I am "+me.toString());
  }
}
test.prototype.toString=function(){
   return "test";
}

test.prototype.say = function () {
  console.log("Hi, I am "+this.toString());
}

var t = new test();
setTimeout(t.say,50);//=window passing functon without ref to this
setTimeout(function(){
  t.say();
},150);//=test passing ref with function
setTimeout(t.sayAgain,200);//=test using me as the saved this context

The second timeout passes a closure to setTimeout, if you're planning to pass the say callback hundreds of times but only create a couple of test object instances then the implementation of the last one (sayAgain) would perform slightly better.

This because you create a closure when you create the test instance but not when passing sayAgain as a callback, if you create many test instances and would not pass say that many times then remove this.me and this.sayAgain from the function body and pass say as a closure.

You can use Function.prototype.bind but it's not supported in IE < 8 and I am not sure if it'll create a closure as in my example using t.say.

Comments

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.