In a nutshell, though I'm sure someone will have a more scientific definition, JCL(Job Controll Language) executes a progam (compiled and linked machine code) within a load library, providing a number of resources to that program: File names (data files, work files), input parameters, and other information, discussed below, within a batch environment, as opposed to a TP monitor like CICS, where jobs are transactions, and all the information a transaction needs is predefined within CICS itself (file names, program names) and by real-time user input.
JCL executes a Job which executes the program directly or invokes a Proc (another set of JCL) to execute the program. Many jobs can call the same Proc, passing different parameters. This provides for some level of reusablity. Jobs reside in job libraries and procs, in proc libraries, or in a configuration management tool which draws this distinction. Input to the program resides in control libraries. Programs reside in source libraries.
JCL is submitted to a job queuing system like JES for OS/390 or POWER for VSE/ESA. The job goes into a input queue, then a run queue, then an output queue. The parameters specified on the JCL 'JOB' card determine how it interacts with the queing system. That is, the job priority (based on a ru n class), how long the job can run, the user id of the submitter of the job (which in a producton environment is a scheduler system), the print class, job accounting info, and more.
The interface to the queuing system, for OS/390 is SDF (natively provided by IBM) or IOF, a third party product.
Hope this helps.