开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜