Often environments are defined by means of the \newenvironment-macro whereby the underlying macros \⟨environmentname⟩ and \end⟨environmentname⟩ are defined.
If an environment is defined this way, then the \begin-macro beneath other things opens up a new scope/group and within that scope/group calls the macro \⟨environmentname⟩ via \csname ⟨environmentname⟩\endcsname.
If an environment is defined this way, then the \end-macro beneath other things calls the macro \end⟨environmentname⟩ via \csname end⟨environmentname⟩\endcsname and afterwards closes the scope/group opened up by the \begin-macro.
\csname ⟨macroname⟩\endcsname delivers the token \⟨macroname⟩. In case the token delivered is not already defined at the time of delivery by \csname..\endcsname, it will be defined equal to the \relax-primitive within the current scope/group. (The \relax-primitive is a non-expandable no-op which makes it into TeX's stomach.)
A token being undefined or being defined equal to the \relax-primitive is the same for \newcommand: If you do \let\foobar=\relax, then you can afterwards perfectly do \newcommand{\foobar}... without getting an error about \foobar being already defined. Actually \newcommand doesn't check if the command to be defined is undefined. \newcommand actually checks if it is the case that the command to define either is undefined or equals \relax. If this is the case, the definition will be performed. If this is not the case, i.e., if the command to define is defined different to \relax, then an error-message about the command in question being already defined is raised.
If a macro \end⟨environmentname⟩ was defined for every environment, then \newcommand forbidding the defining of macros with the phrase "\end" in their name would not be necessary. Checking for (underlying) macros already being defined different from \relax would be sufficient both with \newcommand and with \newenvironment.
The \newenvironment-macro is a nice tool for defining environments but actually the \begin-macro and the \end-macro "don't care" how the defining of underlying macros \⟨environmentname⟩ and \end⟨environmentname⟩ was done.
Sometimes environments are defined not by using \newenvironment but by just defining the underlying \⟨environmentname⟩-macro directly while leaving the \end⟨environmentname⟩-macro undefined, relying on the circumstance that invocation as \csname end⟨environmentname⟩\endcsname via the \end-macro would yield the \relax-no-op as within the scope/group of the current environment the macro \end⟨environmentname⟩ is undefined.
Thus forbidding the defining of macros with \end... in their name prevents accidentally/erroneously defining an \end⟨environmentname⟩-macro for an environment where none should be defined.
\newcommand, since all environments create a macro\end<environmentname>, your definition, if executed, would overwrite a hypothetical environment namednote. You can\def\endnote{}, but you do so at your own risk. – Steven B. Segletes May 25 '21 at 12:14\<environmentname>and\<endenvironmentname>underlying environments I especially like the environmentscsnameandgroup. ;-)) – Ulrich Diez May 27 '21 at 14:11