开发者

Javascript class scope

I am unable to call this.RenderDeals() from inside my Post.success function. I assume this has something to do with scope? Could someone shed some light on the issue, and possibly suggest a workaround. I have tried using prototype and module pattern, both without any luck.

FYI Post is an $.ajax wrapper that returns a jQuery Deferred开发者_如何学JAVA object.

    function Deals() {
        this.template = '#trTemplate';
        this.container = '#containerTable';
        this.GetDeals = function () {
            Post('Deal.svc/GetDeals')
            .success(function (result) {
                this.RenderDeals(result);
            });
        };
        this.RenderDeals = function (deals) {
            $(this.template).tmpl(deals).appendTo(this.container);
        }
    }


    var deal = new Deals();
    deal.GetDeals();

UPDATE:

Ok, so I added the following line just above the GetDeals function:

var me = this;

and instead call

me.RenderDeals(result);

Appears to work correctly, but I'm not sure why.


The this reference in your "success" function almost certainly isn't what you think it is. Try this change:

function Deals() {
    var instance = this;

    this.template = '#trTemplate';
    this.container = '#containerTable';
    this.GetDeals = function () {
        Post('Deal.svc/GetDeals')
        .success(function (result) {
            instance.RenderDeals(result);
        });
    };
    this.RenderDeals = function (deals) {
        $(this.template).tmpl(deals).appendTo(this.container);
    }
}

By stashing a reference to this in the "instance" variable, your handler will have a guaranteed way of getting back to the relevant instance when calling the other function ("RenderDeals").


Firstly, there are no classes in javascript, only objects. This may sound strange, but you can still do OOP without them in javascript :) I suggest you read up on this.

You are correct about the scope issue, the this keyword has some strange behavior. Read this for some more info.

Look into using the prototype attribute of any function object. I prefer to do my javascript OOP in the following fashion:

function Deals(){
    //this is your constructor
    var me = this;
    //this way you can avoid having to search the DOM every time you want to reference
    //your jquery objects.
    me.template = $('#trTemplate');
    me.container = $('#containerTable');
}
Deals.prototype.getDeals = function(){
    var me = this;
    Post('Deal.svc/GetDeals')
    .success(function (result) {
        me.RenderDeals(result);
    })
}
Deals.prototype.renderDeals = function(){
    var me = this;
     me.template.tmpl(deals).appendTo(me.container);
}

By declaring var me = this; at the top of each prototype function, you create a closure that refers to the object of interest, even inside of a callback :)


Why not define RenderDeals() outside of Deals()?

    function RenderDeals(dealsObj, dealsData) {
        $(dealsObj.template).tmpl(dealsData).appendTo(dealsObj.container);
    }

Then instead of this:

this.RenderDeals(result);

Do this:

RenderDeals(this, result);


Try this:

var Deals = {
    template: $('#trTemplate'),
    container: $('#containerTable'),
    init: function (){
        return Deals;
    }
    GetDeals: function () {
        Post('Deal.svc/GetDeals')
        .success(function (result) {
            Deals.RenderDeals(result);
        })
    },
    RenderDeals = function (deals) {
        Deals.template.tmpl(deals).appendTo(Deals.container);
    }
}

var deal = Deals.init();
deal.GetDeals();


You are right, it is a scoping issue. Pointy has the right answer, but I thought I could fill in a bit of what is going on.

this in javascript is an implicit variable that is set to whatever the function is attached to by default (or the global object if it isn't attached to anything). When you pass your function as a param into Post#success, it is not attached to any instance, let alone the current instance of Deals.

Pointy has the best answer here, what he is doing is creating an explicit variable that captures the implicit variable of this of deals. One of the coolest features of javascript is that everything that is in scope of a function definition will also be in scope for a function invocation, so by making that variable, you are able to access it again later, whenever and however that anonymous function is called.

0

上一篇:

下一篇:

精彩评论

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

最新问答

问答排行榜