简体   繁体   中英

this and passing function as parameter in Javascript

I have following Javascript objects:

function Alfa() {
  this.status='';
  this.setStatus = function(value) {
    this.status=value
  }
}

function Beta() {
  this.setSomething = function(setter) {
    setter('Something');
  }
}

And than execution:

alf=new Alfa();
alf.setStatus('foo');

This works fine, if you look into values of alf , the status is set to 'foo', but:

bet=new Beta();
bet.setSomething(a.setStatus);

What I have expected is that bet will execute setStatus function of alf and set status value to 'something', however, this is not happening. setStatus of alf is executed, but this points not to alf instance but to Window , so the property status is set for Window not for alf .

What is the proper approach to get desired functionality?

This is of course simplified implementation, in real life i want to pass those functions of alf to event handlers, so I cannot change Beta implementation, eg:

$('xxx').click(alf.setStatus)

JavaScript functions are unbound. That means this is determined by how it's invoked rather than how it was defined. Because you are invoking the method from within bet , then this is bet

To get around this you need to make a bound function , which creates a stable this no matter how the function is invoked.

If you are using an ES5 compatible JavaScript interpreter then you can use: Function.bind

alf.setStatus.bind(alf)

Or if you arent there are several es5 shims that provide this functionality in older interpreters. In fact one is provided on the mdn reference for bind. JQuery has a version called $.proxy

A simple implementation is that you want a function that takes a function and a scope. And then calls your method in that scope specifically, rather than using this. Something like.

function bind(func,o) { return function() { func.call(o); } }

Functions in JavaScript don't have a context attached to them, like eg bound methods in Python. So what you can do is to call setStatus functions with a context, like this:

bet.setSomething(function(value) {
    a.setStatus.call(a, value);
});

https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/call

Change setter('Something'); to setter.call(this, 'Something'); will be work.

function Alfa() {
    this.status='';
    this.setStatus = function(value) {
        this.status=value
    }
}
function Beta() {
    this.status='';
    this.setSomething = function(setter) {
        setter.call(this,'Something');
     }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM