简体   繁体   中英

Function _.bind() won't bind an object

I have a view class extending SugarCRM CreateView and I want this to be this.model in function checkMonths when the field starting_months_c is changed, so I could type this.get() instead of this.model.get() .

/**
 * @class View.Views.Base.DoVPCreateView
 * @alias SUGAR.App.view.views.DoVPCreateView
 * @extends View.Views.Base.CreateView
 */
({
    extendsFrom: 'CreateView',
    initialize: function(options) {
        this._super('initialize', arguments);
        // ....
        this.model.on('change:starting_month_c', _.bind(this.checkMonths, this.model));
        // ....
    },
    checkMonths: function() {
        if (this.get('starting_month') == 12) {
            // ....
        }
    }

Unfortunately, this construct does not work. I wonder, maybe it is because the .on() function somehow sets the context itself?

I found out in the doc, that you can pass the context to the function as third parameter

object.on(event, callback, [context])

I tried this but the result is still the same - the view is this , not the model .

Quick fix

Give the context directly to .on :

this.model.on('change:starting_month_c', this.checkMonths, this.model);

But doing this is only a misleading fix. The view's functions should all have this being the view instance and not other arbitrary objects.

 // a simple example view var View = Backbone.View.extend({ initialize: function() { console.log("View init, month:", this.model.get('month')); // bind the context this.model.listenTo(this.model, "change:month", this.checkMonth); }, // the callback checkMonth: function() { // here, `this` is the model which you should NOT do. // but for demonstration purpose, you can use `this.get` directly. console.log("checkMonth:", this.get('month')); }, }); // sample for the demo var model = new Backbone.Model({ month: 2 // dummy value }), view = new View({ model: model }); console.log("change month"); model.set({ month: 3 // set to trigger the callback }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/backbone.js/1.3.3/backbone-min.js"></script> 

Real fix

If you always want to trigger a check "months" callback whenever starting_month_c changes in any instance of this model, you could move that into the model class itself.

var Model = Backbone.Model.extend({
    initialize: function() {
        // favor listenTo over `on` or `bind`
        this.listenTo(this, 'change:starting_month_c', this.checkMonths);
    },
    checkMonths: function(model, value, options) {
        if (this.get('starting_month') === 12) {
            // whatever you want
        }
    }
});

If it's only for this specific view, use this.model.get in the callback as it should be . This is not a problem, it's the standard way of doing it.

More info on why to favor listenTo .

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