Scoping problem with Javascript callback

前端 未结 3 1484
眼角桃花
眼角桃花 2021-01-24 11:28

I am having some trouble getting a callback function to work. Here is my code:

SomeObject.prototype.refreshData = function()
{
  var read_obj = new SomeAjaxCall         


        
3条回答
  •  孤城傲影
    2021-01-24 12:09

    Your problem here is not exactly a closure or scoping problem. The problem is that when you assign this.readSuccess to a variable, you assign the function itself without any notion of the object it originaly belongs to.

    In the same way, you can take a regular, "stand-alone" function and use it as method of an object:

    function hello() {
        alert("Hello "+this.planet);
    }
    var planet = "Earth";
    hello(); // -> 'Hello Earth'
    
    var Venus = {
        planet: "Venus"
    };
    hello.apply(Venus); // -> 'Hello Venus'
    Venus.hello = hello;
    Venus.hello(); // -> 'Hello Venus'
    

    And your problem can be replicated in this example

    var helloVenus = Venus.hello;
    helloVenus(); // -> 'Hello Earth'
    

    So your problem is to assign this.readSuccess to some variable and having it called as a method of this. Which can be done with a closure as demonstrated by Pointy. Since I don't know what "SomeAjaxCall" actually does, it's hard to know if the value of this is actually lost and if var obj = this is actually needed. Chances are that it's not, so you can be fine with this kind of code:

    var helloVenus = function() { Venus.hello() }
    helloVenus(); // -> 'Hello Venus'
    

    In your case, that would be (edit: adding the arguments passed to the handler) :

    SomeObject.prototype.refreshData = function()
    {
      var read_obj = new SomeAjaxCall(
        "read_some_data",
        { },
        function () { this.readSuccess.apply(this, arguments) },
        function () { this.readFail.apply(this, arguments) }
      );
    }
    

    As noted previously, several js frameworks offer a bind function to simplify this kind of issue. But you don't need a complete framework just for this : here is a perfectly fine Function#bind method that works an plain javascript:

    Function.prototype.bind = function(obj) {
        var __method = this;
        var args = [];
        for(var i=1; i

    With the help of Function#bind, you can write:

    SomeObject.prototype.refreshData = function()
    {
      var read_obj = new SomeAjaxCall(
        "read_some_data",
        { },
        this.readSuccess.bind(this),
        this.readFail.bind(this)
      );
    }
    

提交回复
热议问题