EXECUTE AS user
If you have a module, e.g. stored procedure, which references many objects (for example, mary.Contact, steve.Address, etc), EXECUTE AS user should be used instead of EXECUTE AS OWNER because the ownership chain is broken.
EXECUTE AS SELF
When Smith creates the GetCustomer stored procedure with EXECUTE AS SELF, the result stored procedure will have EXECUTE AS Smith.
You have a stored procedure script. An application can create the stored procedure from the script. When John runs the application, the stored procedure will have EXECUTE AS John. When Joanne runs the application, the stored procedure will have EXECUTE AS Joanne.
As you see, the result is the same as EXECUTE AS user.
EXECUTE AS CALLER
The user who run the stored procedure must have the permissions on Customer table and have the EXECUTE permission on the storede procedure.
EXECUTE AS OWNER
When Tim runs the GetCustomer stored procedure, the Database Engine verifies that Tim has the EXECUTE permission on the GetCustomer object. When the GetCustomer stored procedure accesses the Customer table, because both Customer table and the stored procedure have the same OWNER (EXECUTE AS OWNER), Database Engine will not check the permissions. When SAM creates the GetCustomer object, SAM is the owner.