You need to understand that each process has a context for its operation - environment variables, working directory, open files, shared memory (and some others but these are the major ones).
The environment variables provided to a process are the "exported list" and are copied from the parent process. This allows new processes to inherit the exported list from the process that starts it. A process may change the values or add new names and values to the exported list. But a process cannot alter the values used by the parent process. The new values can only be used by new processes started (which is when they get copied) AFTER the new/modified values have been set.
Like environment variables, the working directory is also copied to new processes. Also like environment variables, a process cannot change the parents working directory - only its own and that will be inherited by any processes started after the change.
Open files can be a bit tricky. The only ones normally passed from process to process are stdin (file descriptor 0), stdout (file descriptor 1), and stderr (file descriptor 2). It is possible to create others though.
So a script running as a process can change its working directory. If the script is spawned as a new process (the usual case) then it gets a new context. If the parent process wants a script to change its working directory, then it must not spawn a new process - but instead include the script (the "source <filename>" thing) is used to redirect the command input to the <filename> until the <filename> finishes... NOTE: several peculiar looking things things can happen. If the script uses the "exit" command, then the process will terminate, and not go to the next command:
# script for testing.sh
echo before xyz
echo after xyz
If the "xyz.sh" file contains:
echo in xyz
Then you will get the result:
But if the xyz file contains:
echo in xyz
Then you will get
Showing that the process that is running the "testing.sh" script terminated before reaching the end of the script.
Sometimes this is exactly what you want... But if you do it in a ".login" or "bash.rc" file (used during a login, or when you start a shell script) you will get logged out... or the shell will just exit without running your script.