You can "pin" Nixpkgs with this style of invocation as well, see https://nixos.wiki/wiki/Nix-shell_shebang#Pinning_nixpkgs. But I agree that if you're writing a shell script (or small Python/Ruby scripts) that you'll be running often, it's better to package it (e.g. with writeShellScriptBin) and install to profile.
My own rule of thumb is that nix-shell is great for quick one-offs and for sharing environments. For local tools and anything else I’m sharing with my future self, it’s usually better to write a nix expression and install it, which gives me access to Nix’s (excellent) rollback system, and lets me upgrade on my schedule, not upstream’s.
* - ‘Latest’ according to whatever Nix channel checkout currently applies. Which you can change, of course, but the point is it’s external to the script.