Well, you can react on them whenever you want, but yeah. If you use the built-in input events, that's already what you're doing essentially. All of the keyboard and mouse events happen between the Begin Step and the Step events. GM runs on an event-by-event order, not instance-by-instance order, so GM will not run the Step Event until all instances have run their Begin Step events.
Now, going off the boss enemy example...
If the player had its input events and the boss had an input event for the player's attack button, then when the attack key is pressed, both events would run. One input check, two events executed. This is adequate. But if we didn't use the input events, then you'd have the player checking for the attack button and the boss also checking the attack button. So the input check is handled by GM, then the player's input check code is handled, then the enemy's input check code is handled. That's three input checks and two executions, as opposed to just one input check and two executions. If we used the input event in just the player saved to a global or in a control object, then have the player and the boss check the value of that variable, then it'd be one input check and one input event.
But what about the code that needs to be run if the attack key is pressed? In the first method, the player could execute his attack code from the key event; likewise, the boss could activate his defense code from the key event. However, the more common scenario is the key events would set variables in each of the instances and that variable would be referenced in the Step event. And that in and of itself requires additional code to work properly (which is why people rarely do this anymore).
Code:
///Begin Step
key_attack = false;
///Attack Key Input
global.key_attack = true;
///Step
if key_attack {
blahblahblah
}
The Begin Step code would need to be in the boss too. So that's 6 event calls when it could easily just be 4.
Code:
///Control object or Player object (if single-player) Begin Step
key_attack = false;
///Control object or Player object (if single-player) Attack Key Input
key_attack = true;
///Player and Boss Step
if global.key_attack
{
blahblahblah
}
It gets even more important when you start dealing with multiple inputs. And if you are using gamepads, you don't even have events (or maybe you do in Studio 2? I dunno, I use S1). In those scenarios, the fewer input calls you make, the better. What if the attack input is configurable so that it could be either the mouse or the keyboard, or both?
Code:
key_attack = 0;
if input_attack = enums.keyboard
key_attack = keyboard_check(io_attack);
else
key_attack = mouse_check_button(io_attack);
You'd need to run that for both the player and the boss, or you make key_attack a shared variable and only run that code once in a Begin Step. You wouldn't be running any input events in this case.
You can further condense things by using a single variable to hold all input states (via bit manipulation), but you'd be sacrificing some speed to save on the array size.