Javascript: How can an object store a reference to another object's method, and call it "remotely"?
So, I got two objects, a and b. Now, I want to pass one of b's methods to the a object, wich should store it. Let's call that method b.met:
b.met=function(){
alert(this.txt);
}
Now, I want to call b.met from a. The following code doesn't work, since a.met is a clone of b.met inside the scope of a:
a.met=b.met;
a.met(); //Executes in the 'a' scope!
The only way I found, by now, is to save the method's name in a string and use it in an eval statement:
a.toCall='b.met';
eval(a.toCall+'();');
Since everyone says you should avoid using eval... what other possibilities are there?
EDIT - see in comments: So I changed my code from:
a:{
processes:[],
spawnPro开发者_开发技巧cess:function(type,id,closeFn){
var closeFn=closeFn || 'function(){}';
this.processes.push({type:type,id:id,closeFn:closeFn});
}
to:
a:{
processes:[],
spawnProcess:function(type,id,closeFn){
var closeFn=function(){closeFn()} || 'function(){}';
this.processes.push({type:type,id:id,closeFn:function(){closeFn()}});
}
When executing the following code, I get a too much recursion error:
a.spawnProcess('','',b.met);
a.processes[0].closeFn();
Your storing a reference to a function. A function is just a function. It get's it's definition for this
based on the calling context.
So if you store a.met = b.met
and then call a.met()
inside that function this === a
Read up at the JavaScript garden about this
What you want to do is store the function and the context to call it in.
This can be done either as
a.met = function() {
b.met();
}
or
a.met = b.met.bind(b);
.bind
requires ES5. Recommended cross browser alternatives include _.bind
and $.proxy
Edit
You need to change
a.spawnProcess('','',b.met);
to
a.spawnProcess('','', function() {
b.met();
});
You probably also want this instead
a: {
processes: [],
spawnProcess: function(type, id, closeFn) {
this.processes.push({
type: type,
id: id,
closeFn: closeFn || function() {}
});
}
}
Simplest solution:
a.met = function() { b.met(); };
or using .bind
(see MDC), same semantic:
a.met = b.met.bind(b);
If your functions are many and they have arguments you can also do this
function B() {
this.x = "I am b";
}
function A() {
this.x = "I am A";
}
B.prototype.met = function() {
alert(this.x);
}
A.prototype.met = B.prototype.met;
You can update A.prototype with functions that you need from B.prototype.
精彩评论