Referring to the 12 rules, it’s a question of how many times things are evaluated. In the first example, the command is broken into words, and then catch will evaluate expr 1/0 – this 2nd evaluation is just like the first: break it into words, substitute variables, etc.
In the 2nd example, the braces delay variable substitution. So catch gets $script. It evaluates that into the string “expr 1/0”, but there is no 3rd evaluation, so it attempts to execute that string as a command.
As you’ve seen, adding eval gives you that 3rd round of evaluation.
The simpler approach is to omit the braces: catch $script result