Binding and event handler — passing the event object
Asked Answered
M

2

8

I have some sample code which binds an event handler as follows:

var h1=document.querySelector('h1');
h1.onclick=doit;

function doit(x) {
        console.log(x);
}

When the event handler is triggered (by clicking on the h1 element), the output is an event object, as expected.

If I bind the event handler as follows:

h1.onclick=doit.bind(h1);

I get the same result.

However, if I bind it as follows:

h1.onclick=doit.bind(h1,1);

I get 1, the first parameter after h1. In all cases, the vallue of this is correctly set to h1, but in the last case, the passed parameter appears to replace the expected event object.

How can I keep the event object without rewriting the event handler as a function expression?

Mckinzie answered 26/5, 2016 at 1:40 Comment(1)
It does not replace it, it does precede it (the event will be passed as second argument). But if you want the event in the first parameter, just don't partially apply the function (don't bind arguments to it).Halfhearted
P
11

but in the last case, the passed parameter appears to replace the expected event object.

Using bind creates a function with pre-specified initial arguments.

MDN Docs:

These arguments (if any) follow the provided this value and are then inserted at the start of the arguments passed to the target function, followed by the arguments passed to the bound function, whenever the bound function is called.

Which means, if you do:

h1.onclick=doit.bind(h1,1);

The value of this is bound to h1 as you've mentioned but the event from the onclick is passed as the second argument to doit, instead of first, since you bound 1 to the first argument. So you are still getting the event, it isn't getting replaced, it's just passed after all the bound arguments.

How can I keep the event object without rewriting the event handler as a function expression?

You can't. The event will be passed after all the arguments you previously bound to the function so you must take that into account. For the given case, doit would look like:

function doit(one, e) {
  console.log(this, one, e); // on click logs: h1 object, 1, event object
}
Piecemeal answered 26/5, 2016 at 1:57 Comment(2)
So the doit function should be something like doit(x,e). OK, that works, as long as I don’t allow for optional parameters which will make a mess of the whole thing. Thanks.Mckinzie
No problem, glad to help :)Piecemeal
E
0

If you check out this link it says that the arguments after the first argument becomes the first argument passed to the function.

If you call it with just the h1 element, all you're doing is binding the function to that h1 element. If you pass anything else in that second parameter it will become the first argument passed to function.

Examples

function testing(a, b, c) {
  console.log(this.property, a, b, c);
}

var obj = {
  property: 'value!'
};

var bound_test = testing.bind(obj, 'Bound Test A');
bound_test('test 1', 'checking console output');
bound_test() // should give two undefined in console since we are only giving the first object.

var bound2_test = testing.bind(obj, 'Bound test B', 'something ');
bound2_test('this will be the "c" argument');

var bound3_test = testing.bind(obj, 'Bound test C', 'Test', ' another, yet different test.');
bound3_test();
Ethylene answered 26/5, 2016 at 1:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.