jashkenas / backbone

Give your JS App some Backbone with Models, Views, Collections, and Events
http://backbonejs.org
MIT License
28.09k stars 5.38k forks source link

.bind() ambiguity #170

Closed dvv closed 13 years ago

dvv commented 13 years ago

Hi!

Am constantly confused by Model.bind('event', handler) which is by sense what they'd call Model.on('event', handler)...

The word "bind" seems to be more associated with JS Function#bind -- in particular Underscore#bind()/Underscore#bindAll().

Thus the constructions like _.bindAll(this, 'render'); this.bind('change', render);

which are common in .initialize() code are a bit confusing.

I'd suggest to get rid of word "bind" in event binding code in favor of "on" -- _.bindAll(this, 'render'); this.on('change', render);

What do you think? TIA, --Vladimir

maritz commented 13 years ago

Once again this probably comes from jquery (or similar) where .bind is used for events.

However in this case I have to agree. Using .bindAll and .bind is confusing and changing it to .on would be okay.

martindrapeau commented 13 years ago

I agree there is a little confusion but as a jQuery user, I would argue to keep bind for events, and change Underscore bind and _bindAll to context and contextAll or something like that. In either case, such a change would break backwards compatibility. I'm not sure it's worth the trouble. My two cents.

dvv commented 13 years ago

There's no need to break underscore -- its bind/bindAll deal with Function object. Instead consider aliasing Backbone.Events#bind as Backbone.Events#on, so both would be ok. Then mark Backbone.Events#bind as deprecated, possibly with console.log('deprecated') stub. That could be the way

tauren commented 13 years ago

+1 Totally agree this is confusing. It's too bad underscore and jquery use "bind" to mean two different things. It would be nice if jquery, underscore, and backbone all could have similar APIs.

I think this could happen, especially since two out of the three libraries are managed by DocumentCloud. Obviously, there isn't a way to change jquery at this point, especially with its massive user base. I reluctantly agree with @martindrapeau that a name change in Underscore would be preferred so as to not dilute the meaning of "bind". This could be handled with an alias as well so as to not break existing code, but mark "bind" as deprecated.

I say "reluctantly" because I really do prefer "on" to "bind" when dealing with Events. And leaving Underscore alone would certainly be simpler and easier, as it has a much larger install base than Backbone. The simplest solution, as suggested by @dvv, is to alias Events#bind to Events#on, since only Backbone needs to be changed. Since backbone is fairly new, its not too late to change the recommended approach to use Events#on instead of Events#bind, yet keep bind deprecated for backwards compatibility.

Bottom line is something should be done. Which approach is taken is of less importance as long as two different "bind" methods with different meanings aren't being used right next to each other in initialize(). That could be dang confusing to less experienced developers.

cristibalan commented 13 years ago

Just want to add a note about the deprecation with console.log.

I've recently had my app break for Firefox users who didn't have firebug installed when using console.log. So, if you take this route, please make sure console.log exists as a function.

kirbysayshi commented 13 years ago

I also agree that the bind ambiguity is horrible. Honestly, the 'official' definition of bind is more inline with underscore's and Function.bind, so even though jQuery is huge, I believe the proper definition of bind should be used. Thus, I would prefer 'on', 'attach', 'listen', or whatever, anything but bind for events.

On a side note: thanks for a great library! While it's difficult to think in this pattern at first, I adore the structure it brings.

JesseAldridge commented 13 years ago

+1 As a new user, I was really confused by this.

KaptajnKold commented 13 years ago

I vote for changing to 'on'.

As of EcmaScript 1.8.5, 'bind' is a method on the function prototype. We should accept this and move away from the jQuery convention. (see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind)

vibornoff commented 13 years ago

+1 for on

sstephenson commented 13 years ago

Here's a patch I worked up a while ago to make Backbone.Events more like Node's EventEmitter: https://github.com/sstephenson/backbone/compare/events

josh commented 13 years ago

on :heart:

nicolasblanco commented 13 years ago

:heart: on too!

desaperados commented 13 years ago

.on +1

shesek commented 13 years ago

+1 on renaming it due to ambiguity, but I personally don't like on(). What about publish() and subscribe()?

eastridge commented 13 years ago

+1

I'd also like to see delegateEvents() accept non DOM event handlers:

events: {
  'click a': '_handleClick',
  'viewEvent': '_handleViewEvent'
}
eastridge commented 13 years ago

I also thinking aliasing is the correct solution. Deprecate but don't remove bind

lukeholder commented 13 years ago

+1 ON

PaulUithol commented 13 years ago

As of version 1.7, jQuery will also be supporting / moving to on and off for events; see http://blog.jquery.com/2011/09/28/jquery-1-7-beta-1-released/ :

New Event APIs: .on() and .off()

Over time, jQuery has evolved three ways to attach events to elements: .bind() , .live(), and .delegate(). Underneath it all, though, the three event APIs call the browser’s event system; that can lead to surprising interactions. For example, $(document).unbind("click") will remove all .live("click", ...) events, since those delegated events are attached to document. (This is also why you should use event namespaces.)

Our current event APIs aren’t going away soon, but to address the inconsistencies we’ve introduced a new and simple pair of event methods that can do the work of all three:

$(elems).on(events, selector, data, fn); $(elems).off(events, selector, fn);

If a selector is provided, it’s a delegated event; otherwise it’s directly bound. All the features of the old APIs are there; for example events can be a space-separated string of event names and/or namespaces, or it can be an object where the keys are events and the values are event handler functions.

So, looks like a good time to start supporting this in Backbone as well to me ;)

tbranyen commented 13 years ago

Currently tracking here: https://github.com/documentcloud/backbone/issues/641