jashkenas / backbone

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

events registering handlers with hash and context #4214

Closed taburetkin closed 5 years ago

taburetkin commented 5 years ago

Hi there. I believe it's not an issue but rather a question

the docs says:

To supply a context value for this when the callback is invoked, pass the optional last argument: model.on('change', this.render, this) or model.on({change: this.render}, this).

i have this example: https://codepen.io/dimatabu/pen/zXgQjE

const a = { a:1 };
const b = { b:1 };
const c = { c:1 };
const handler = function(){
  console.log(this, ...arguments);
}
Backbone.on({ 'a': handler }, a, b, c);
Backbone.trigger('a', 1, 2, 3);

the console output is: {b:1}, 1, 2, 3 and i want to understand • what happens with a and c arguments when i bind a handler in such way ? • it seems that b is not last argument as noticed in docs, the last one is c, so docs are a little bit incorrect? • what for this at all? (because there is even a test for that, but suddenly its not clear from test why this should be like that)

edit: i can understand if the output will be {a:1}, 1, 2, 3 or {c:1}, 1, 2, 3 the last one actually not clear for me, but at least it corresponds the docs.

and the last one with this registration: Backbone.on('a', handler, a, b, c); output will be {a:1}, 1, 2, 3, why there is a difference between string and hash handler registration?

with regards.

jgonggrijp commented 5 years ago

The documentation gives you two method signatures to choose from:

You are doing something that matches neither signature:

({name: callback}, context, context, context) => ?

so you are violating the preconditions of the method. This is also called breaking the contract. In general, you cannot expect a piece of software to do what it is supposed to do if you break the contract.

I do agree the result is a bit surprising. Purely out of academical interest, I had a look in the annotated source to see what's going on. It appears that the implementation of Events.on relies first and foremost on the number of arguments. If you pass a third argument (b in your case), the implementation concludes you must be invoking the first signature of the method, so that third argument must be the context.