The very short version is: you are not executing the file. You are reading it into the shell, which then executes it.
Note that some language interpreters check the execute permissions of a file they are being asked to execute and will refuse to do so if the user doesn't have appropriate permissions. But that is a completely discretionary check by the author of that particular interpreter, and is not enforced by the operating system.
Let's make a little thought experiment.
I think we can both agree, that if a program has executable permissions, I should be allowed to execute this program. I think we can also agree that this program should be allowed to print the string "Hello World" to the console.
Further, we can probably also agree that a program should be able to read a file as long as that file has read permissions. And it doesn't really matter what the content of that file is, as long as the file has the read permission bit set, the program should be allowed to read it.
Okay, so, since we have agreed that the program should be allowed to print "Hello World" to the console and we have agreed that the program should be allowed to read the file, you must logically also agree that the program should be allowed to read the file and print "Hello World" to the console. And we have also said that whether or not the program is allowed to read the file depends on the permissions, and not on the content, so it should also be allowed to read the file and print "Hello World" to the console if the content of the file is echo Hello World
.
Now, can you also agree that since the program is allowed to read the file and since the program is allowed to print "Hello World" to the console, that it is also allowed to check the content of the file and only print "Hello World" to the console if the content of the file is echo Hello World
?
Well, but then it is "interpreting", in other words executing the file, and you have just agreed with me on every step of the way that it should be allowed to do that!
And that is exactly what is happening here. The shell is simply reading a text file, which it is allowed to do because the text file has read permissions. And the shell is executing the instructions in the text file, which it is allowed to do because the shell has execute permissions.