Scripts help keep code organized by limiting duplicate code. You can use scripts to slightly speed up code by forcing it to break and moving on to the rest of the event (by returning out of the event).
In legacy versions of GM, since GM wasn't very user friendly with its search functionality, scripts were about the only way to code in legacy versions without pulling your hair out. There was also a lot more recursion allowed back then, too (which wasn't necessarily a good thing), so scripts could just keep calling themselves over and over until certain conditions were met (such as the program running out of memory). Studio forces you to be a bit little more cautious with recursive scripts nowadays.
Storing a set of values in arrays or data structures is a bit faster than using switch-return scripts, but you can use scripts as giant libraries/dictionaries of values to be returned indexed by whatever argument(s) you pass to the script. The data retrieval is slower, but takes up less memory.
Calling a script is minutely slower than just running the code itself, but the loss of speed is made up for by the ease of use and memory saved (for scripts called in multiple places).
Consider a code like:
image_xscale = sign(player.x-x | 1);
if sign(hspd) != image_xscale hspd *= -1;
You could put that in every enemy object, or put it in a script and just call the script from every enemy object. Instead of two lines copy-pasted, you have just 1 line copy-pasted.
Suppose you have 20 different types of enemies and each is initialized with its own values for certain variables. For example:
hp = 10;
atk = 1;
def = 1;
level = 1;
image_xscale = sign(player.x - x | 1);
spd = 1;
hspd = image_xscale * spd;
vspd = 0;
alarm[0] = 64;
hp = 22;
atk = 3;
def = 5;
level = 4;
image_xscale = sign(player.x - x | 1);
spd = 2.5;
hspd = -image_xscale * spd;
vspd = 1;
alarm[0] = 1;
And so on. You could copy-paste-edit or type all that out for all enemies, or you could make a script that looks up the object_index of the enemy and assigns the values automatically itself.
Scripts are also indexed like any other resource, so you can call them indirectly rather than looking them up for direct calls. I haven't tested, but I'm pretty sure child scripts (script tabs) are immediately indexed from the parent script, so they should all be indexed in immediate successive order. So if you had a state machine in place with each child script holding the code for a particular state, then you could just do:
script_execute(myStates+state);
...where myStates is the ID of the parent script and state is the numerical reference (from 0) of the current state.
In most cases you don't have to use scripts and they are usually unnecessary, but once in a while it will just make sense to use a script or scripts instead of typing out longer codes.