Cuando se pulsa un enlace en HTML, se espera que ocurra algo. Puede que ese enlace te lleve a otro sitio (un enlace normal) o
presente el resultado en otro marco o página.
Pero si lo que queremos es que el resultado salga en otra parte de la estructura de la página, necesitamos crear un código JavaScript que haga la llamada, obtenga el html del resultado y lo coloque en el contenedor (capa, celda, imagen, etc.) que deseemos.
El desarrollo con FRAMES (y con IFRAME) permite tener unos contenedores HTML separados (realmente, son páginas web independientes), así que la programación del comportamiento es muy sencilla (solo hay que llamar al enlace y el navegador hará el resto). El problema es que son páginas difíciles de indexar y por eso han caído en desgracia desde hace muchos años. Por eso lo de usar JavaScript para realizar el proceso de llenar una capa (un <div>) desde un recurso distinto a la página principal sin que el navegador tenga que redibujar la página entera.
Es precisamente ese también el funcionamiento de las páginas de finales de los años 90: cada petición del usuario se traducía en una composición y envío de toda la página. La programación era sencilla, pero para el usuario, podía ser desesperante ver la recarga de toda la página cada vez que pulsaba algo.