最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Backbone this confusion - Stack Overflow

programmeradmin2浏览0评论

I have the following code:

var GoalPanelView = Backbone.View.extend({

    // Bind to the goal panel DOM element
    el: $("#sidebar-goals"),    

    // Initialize the collection
    initialize: function() {
        this.collection = Goals;
        this.collection.bind('add', this.appendItem);
    },

    // Create a new goal when a user presses enter in the enter goal input
    createOnEnter: function(e) {
        if (e.keyCode != 13) return;
        this.addItem();
        //Goals.create(this.newAttributes());           
    },

    // Add the goal item to the goal list
    addItem: function() {
        var goal = new Goal();
        goal.set(this.newAttributes());
        var goalsElem = this.el;
        this.collection.add(goal);
        $(this.el).children("#enter-goal").val('');
    },

    // Append DOM element to the parent el
    appendItem: function(item) {
        var goalView = new GoalView({
            model: item,
        });
        $(this.elem).append(goalView.render().el);
    }

});

My problem is inside of the appendItem function. When I use this inside of the appendItem function, I believe that it thinks that the this refers to the this.collection rather than the GoalPanelView. How would I get the this to refer to the GoalPanelView rather than the collection? I tried to pass another variable into the appendItem function which held the contents of this.elem, but it didn't seem to work.

One thing that worked was when I moved the appendItem function into the collection and changed the initialization to bind to this.collection.bind('add', appendItem); but I do not want to put the view stuff into the collection logic.

I have the following code:

var GoalPanelView = Backbone.View.extend({

    // Bind to the goal panel DOM element
    el: $("#sidebar-goals"),    

    // Initialize the collection
    initialize: function() {
        this.collection = Goals;
        this.collection.bind('add', this.appendItem);
    },

    // Create a new goal when a user presses enter in the enter goal input
    createOnEnter: function(e) {
        if (e.keyCode != 13) return;
        this.addItem();
        //Goals.create(this.newAttributes());           
    },

    // Add the goal item to the goal list
    addItem: function() {
        var goal = new Goal();
        goal.set(this.newAttributes());
        var goalsElem = this.el;
        this.collection.add(goal);
        $(this.el).children("#enter-goal").val('');
    },

    // Append DOM element to the parent el
    appendItem: function(item) {
        var goalView = new GoalView({
            model: item,
        });
        $(this.elem).append(goalView.render().el);
    }

});

My problem is inside of the appendItem function. When I use this inside of the appendItem function, I believe that it thinks that the this refers to the this.collection rather than the GoalPanelView. How would I get the this to refer to the GoalPanelView rather than the collection? I tried to pass another variable into the appendItem function which held the contents of this.elem, but it didn't seem to work.

One thing that worked was when I moved the appendItem function into the collection and changed the initialization to bind to this.collection.bind('add', appendItem); but I do not want to put the view stuff into the collection logic.

Share Improve this question edited Jan 19, 2016 at 22:32 ElChiniNet 2,9023 gold badges22 silver badges28 bronze badges asked Mar 26, 2012 at 23:57 egidraegidra 9,08721 gold badges67 silver badges92 bronze badges 1
  • 2 An alternative is putting _.bindAll(this) in your initialize function. That ensures that any function called within the object will be applied with the value of this bound properly to the object itself. Useful if you're writing lots of callbacks. – rybosome Commented Jul 30, 2012 at 6:02
Add a ment  | 

3 Answers 3

Reset to default 6

You can add a scope when binding an event handler, like so:

this.collection.bind('add', this.appendItem, this);

The scope sets the value of this inside the handler. In you case, the current object.

Edit: Javascript Garden has a great explaination why this.appendItem does not actually carry the scope of the function itself, it's just a function pointer, not a method pointer. One of the quirks of Javascript..

Edit 2 Backbone Reference - Events / on

Just to update (as of Backbone 0.9.2), the proper way to do this is:

initialize: function() {
    this.collection.on("add", this.appendItem, this);
    ...
}


Depending on your use case, you may also want to consider:

initialize: function() {
    this.listenTo(this.collection, "add", this.appendItem);
    ...
}

You can also use underscore's _.bindAll function in your initialize method:

initialize: function() {
   _.bindAll(this);
   this.collection = Goals;
   this.collection.bind('add', this.appendItem);
}

Now any call to any method on GoalPanelView (e.g. appendItem) will be scoped such that references to this refer to the GoalPanelView instance.

You can also pass in a list of method names as strings if you don't want to scope all the methods of GoalPanelView

See here: http://underscorejs/#bindAll

发布评论

评论列表(0)

  1. 暂无评论